mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-04-07 03:07:19 +00:00
Compare commits
415 Commits
v0.7.4
...
copilot/cr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1ec9de6f5 | ||
|
|
c9951a24a4 | ||
|
|
b246ce4b0c | ||
|
|
9c04867fd0 | ||
|
|
3c99667577 | ||
|
|
4fd384bacd | ||
|
|
0cd90760ac | ||
|
|
7837940cba | ||
|
|
2dfd4f39ba | ||
|
|
aa41b27c94 | ||
|
|
61429d1dae | ||
|
|
a7b437fedb | ||
|
|
0abc77b56a | ||
|
|
43c23cb4c8 | ||
|
|
6d0168add6 | ||
|
|
0cb11fc4aa | ||
|
|
9f625748ed | ||
|
|
ab1fa7198a | ||
|
|
21f806c625 | ||
|
|
03e0202a3d | ||
|
|
cc8cb0163e | ||
|
|
fbf122d79c | ||
|
|
a08d6c573e | ||
|
|
a6b830b1af | ||
|
|
b9a14a954d | ||
|
|
c4786ec22d | ||
|
|
aec29b28ba | ||
|
|
0fb9f09997 | ||
|
|
be3ef3b6ed | ||
|
|
a4ad86ab8a | ||
|
|
e8bb2380fb | ||
|
|
3b57e6ffd7 | ||
|
|
45e3a5dbf1 | ||
|
|
2b7656715c | ||
|
|
1f91adc9c8 | ||
|
|
5358b5c085 | ||
|
|
eb8d2b6076 | ||
|
|
6516195264 | ||
|
|
70b01d4d18 | ||
|
|
0515880bf2 | ||
|
|
26cd514fc2 | ||
|
|
3d0e3ab600 | ||
|
|
7f626f1d3a | ||
|
|
1ecee48c70 | ||
|
|
730151cb44 | ||
|
|
bbbb9a2aa1 | ||
|
|
33e9dd69f5 | ||
|
|
aaa3ec42bc | ||
|
|
073070aba8 | ||
|
|
370c956040 | ||
|
|
00e3ac68cc | ||
|
|
9c02af5fbe | ||
|
|
abc03ad342 | ||
|
|
768b3340c1 | ||
|
|
5fcf8dd445 | ||
|
|
dbedb159e4 | ||
|
|
7e2dc68561 | ||
|
|
866b600944 | ||
|
|
53a4f5dcc6 | ||
|
|
72153ee85d | ||
|
|
b8d385229e | ||
|
|
7efaa9eb46 | ||
|
|
87aad43aee | ||
|
|
1acf63c411 | ||
|
|
a42d910ba1 | ||
|
|
8eea90731c | ||
|
|
5bcfdd058d | ||
|
|
cd0675e8a3 | ||
|
|
e19575bcbd | ||
|
|
c06f54a3a3 | ||
|
|
cd5e2a82e1 | ||
|
|
2583215e8b | ||
|
|
8ceb375310 | ||
|
|
b0e086464d | ||
|
|
ad38a28468 | ||
|
|
f44b8b2b29 | ||
|
|
c832f56683 | ||
|
|
4b35b1e456 | ||
|
|
40cb5bdeeb | ||
|
|
936a152d39 | ||
|
|
f28ac63398 | ||
|
|
711cef90c8 | ||
|
|
b9a20a1e24 | ||
|
|
007cea96f4 | ||
|
|
584d372521 | ||
|
|
dd39e1a6d5 | ||
|
|
2f9e6c15e8 | ||
|
|
2ffffff8c9 | ||
|
|
d812a0c722 | ||
|
|
beb1cd3de4 | ||
|
|
0aeac4a414 | ||
|
|
a51804b441 | ||
|
|
7a6a3c753d | ||
|
|
281984e9a3 | ||
|
|
a270d6797a | ||
|
|
6e8405d5f0 | ||
|
|
84b8c3e8e6 | ||
|
|
eed8baf4f6 | ||
|
|
19fb89b1c1 | ||
|
|
5899e6d9a1 | ||
|
|
bdc8cf71b9 | ||
|
|
1d0ae05a0e | ||
|
|
550f3cc074 | ||
|
|
7e7d9d02c6 | ||
|
|
581a8fe60e | ||
|
|
be99fc56b7 | ||
|
|
55a9afc986 | ||
|
|
3c5708a37f | ||
|
|
017e580ec8 | ||
|
|
78af6c5467 | ||
|
|
7f9e5b80c6 | ||
|
|
7cc55aab00 | ||
|
|
a37ee54f4e | ||
|
|
9e73320e04 | ||
|
|
92d73ae7c9 | ||
|
|
866c69ffc3 | ||
|
|
dd5b3df95a | ||
|
|
189def747d | ||
|
|
634ed49694 | ||
|
|
1267602a1b | ||
|
|
009b34b78e | ||
|
|
b5bdc75a63 | ||
|
|
135077aef8 | ||
|
|
9537c06ee4 | ||
|
|
63eb807cec | ||
|
|
7e9719ac5e | ||
|
|
375062f3e9 | ||
|
|
1fa7ab03c9 | ||
|
|
628c2cefbe | ||
|
|
7dc2538d9b | ||
|
|
b531a8628d | ||
|
|
b8dd20c328 | ||
|
|
b2910990a2 | ||
|
|
8867f9722c | ||
|
|
2261ea6f4e | ||
|
|
d1e0ac5be6 | ||
|
|
ba15a83f94 | ||
|
|
40d17bcdba | ||
|
|
0863915307 | ||
|
|
97f05c062c | ||
|
|
66d304ab92 | ||
|
|
5d07cc29a4 | ||
|
|
deb4db72a1 | ||
|
|
51518679f6 | ||
|
|
c7b672cde5 | ||
|
|
e7da3b080a | ||
|
|
800d49c7f8 | ||
|
|
d342fad60f | ||
|
|
beafe09f71 | ||
|
|
ea2b6ec1e3 | ||
|
|
7ccb64dc47 | ||
|
|
e6de39d920 | ||
|
|
b1d0f8b441 | ||
|
|
a5e79a43b5 | ||
|
|
89e8da3ac9 | ||
|
|
66b3c6971c | ||
|
|
1e8cf5dc1f | ||
|
|
f8f237d585 | ||
|
|
c901412df1 | ||
|
|
d865df2b2b | ||
|
|
ef83abdfe8 | ||
|
|
8254c55848 | ||
|
|
14e09ead3c | ||
|
|
5ac0f83c5a | ||
|
|
9a2effd74e | ||
|
|
b8f7d5a227 | ||
|
|
3b6ac1f377 | ||
|
|
e983c51a0a | ||
|
|
ef63830907 | ||
|
|
4878e1ab1f | ||
|
|
611a7eba8e | ||
|
|
bae5d23ccb | ||
|
|
9bd18d5f08 | ||
|
|
b88f21478c | ||
|
|
72a6148896 | ||
|
|
9965b6ce70 | ||
|
|
bdf34ee026 | ||
|
|
d271031b7c | ||
|
|
3a6de640bf | ||
|
|
7793f5a8a1 | ||
|
|
1942dd4835 | ||
|
|
dd70ac2b9f | ||
|
|
9fa1abac65 | ||
|
|
a2e4e00724 | ||
|
|
ee5c8f02ed | ||
|
|
7542ebda5e | ||
|
|
e2418ab095 | ||
|
|
b9dc782c47 | ||
|
|
d7097b5750 | ||
|
|
2c210ae4db | ||
|
|
54e80f8df1 | ||
|
|
7d617aee47 | ||
|
|
bb8a5110ec | ||
|
|
6e0cae7185 | ||
|
|
c65a142e83 | ||
|
|
f60e52d633 | ||
|
|
3c1c5f2039 | ||
|
|
7613886c61 | ||
|
|
284a560c45 | ||
|
|
a01860d206 | ||
|
|
8bb015921c | ||
|
|
7355cff4ab | ||
|
|
460e935643 | ||
|
|
cad3fb63cf | ||
|
|
58b702d20f | ||
|
|
cab3ba50e1 | ||
|
|
8dbbe3c4c4 | ||
|
|
506152b168 | ||
|
|
0b9bc525ad | ||
|
|
9d25b8dccb | ||
|
|
15a09e4831 | ||
|
|
b85d95e364 | ||
|
|
6bee346d43 | ||
|
|
cb029a1d70 | ||
|
|
8ba8aa7ecc | ||
|
|
508550bf1a | ||
|
|
ff539b0b5b | ||
|
|
2f768d22f3 | ||
|
|
5abf8542bb | ||
|
|
05643f77bc | ||
|
|
651305725d | ||
|
|
920d8dd587 | ||
|
|
49e92ecf89 | ||
|
|
443fe213bf | ||
|
|
5ba3f421da | ||
|
|
59cba2fa70 | ||
|
|
5a07138091 | ||
|
|
67b5c3e880 | ||
|
|
1f4fcce977 | ||
|
|
100454d303 | ||
|
|
074eb40734 | ||
|
|
1336ebe9c3 | ||
|
|
13d37b28be | ||
|
|
ca9323518f | ||
|
|
e1f47feade | ||
|
|
24543aa13a | ||
|
|
73cc0917ee | ||
|
|
06614c9d86 | ||
|
|
b3bfead6a0 | ||
|
|
1b415d4931 | ||
|
|
0ab0135977 | ||
|
|
b22adc424f | ||
|
|
a31259ad9b | ||
|
|
13208208d6 | ||
|
|
dda7393c3f | ||
|
|
c7dbb44aaf | ||
|
|
1e3b62bf83 | ||
|
|
30168db4fa | ||
|
|
9d6d68c519 | ||
|
|
3bac2b6f0e | ||
|
|
cdca11f0b9 | ||
|
|
10eeecc6a3 | ||
|
|
e234200d1c | ||
|
|
bdcae3af42 | ||
|
|
698c3d5e3d | ||
|
|
135af0cba5 | ||
|
|
0df9e58313 | ||
|
|
cb0d06c322 | ||
|
|
3c0545f2a6 | ||
|
|
951f7f9918 | ||
|
|
61e2144d15 | ||
|
|
4f329a9c95 | ||
|
|
f1038911e2 | ||
|
|
9481b8ff80 | ||
|
|
5a15324108 | ||
|
|
4f7ae03241 | ||
|
|
2b92dac4cd | ||
|
|
f408a79b2d | ||
|
|
4e07b95155 | ||
|
|
49f0ae0826 | ||
|
|
406d285742 | ||
|
|
4be16d5ba5 | ||
|
|
90b3434b17 | ||
|
|
1ab4eb677b | ||
|
|
797deaf48f | ||
|
|
ccc0feec0a | ||
|
|
020c0ef8f6 | ||
|
|
90049844f3 | ||
|
|
1ce9dca14c | ||
|
|
255c71e9bd | ||
|
|
30408c9036 | ||
|
|
643b7390d1 | ||
|
|
6bbcede4b2 | ||
|
|
46d519d1f4 | ||
|
|
ebfa654b69 | ||
|
|
34cadd42d2 | ||
|
|
134780f149 | ||
|
|
42354761ea | ||
|
|
838cc5f969 | ||
|
|
0b9db34735 | ||
|
|
eb121a91f2 | ||
|
|
91b4266573 | ||
|
|
6501745fc4 | ||
|
|
c33d8a5b34 | ||
|
|
95d471d40f | ||
|
|
444a468a66 | ||
|
|
04a846ad4e | ||
|
|
e4d7f72d17 | ||
|
|
db709d56f7 | ||
|
|
4a6fd78f61 | ||
|
|
b0c76344a0 | ||
|
|
76f29e620c | ||
|
|
e8e9c8b6ad | ||
|
|
c7d8fc555d | ||
|
|
eaa85aba7d | ||
|
|
df6bb2f7dc | ||
|
|
3682283352 | ||
|
|
13575af1d8 | ||
|
|
703c7b9a10 | ||
|
|
6048754840 | ||
|
|
ee2eac9010 | ||
|
|
2fb2c79107 | ||
|
|
359dbf55cb | ||
|
|
99bfc88f06 | ||
|
|
e4f426b979 | ||
|
|
387aa91d07 | ||
|
|
288f08e735 | ||
|
|
972ddcee44 | ||
|
|
c8377d51f1 | ||
|
|
d3b435c353 | ||
|
|
fe2cc4c8f7 | ||
|
|
78c9b285c1 | ||
|
|
0a65b106ad | ||
|
|
373df97629 | ||
|
|
ceaa272d44 | ||
|
|
3c267c9362 | ||
|
|
2113f793c0 | ||
|
|
de41fcb6f2 | ||
|
|
82eea46952 | ||
|
|
c0cfa86497 | ||
|
|
a6f38583b3 | ||
|
|
5c3b014059 | ||
|
|
c7237f802b | ||
|
|
f143abc481 | ||
|
|
4b3a813f27 | ||
|
|
77de23d73b | ||
|
|
02d13889e9 | ||
|
|
a60ebfac5e | ||
|
|
7d0a4c58fd | ||
|
|
e1699a90b1 | ||
|
|
4e4a0c10bb | ||
|
|
0565c5ee85 | ||
|
|
8bb1cad898 | ||
|
|
06850f4ccb | ||
|
|
9130cad7d6 | ||
|
|
2c0348195b | ||
|
|
e14c030db0 | ||
|
|
dc4b9049b3 | ||
|
|
452afd0807 | ||
|
|
fdba17099c | ||
|
|
cc6bd2c05d | ||
|
|
b44e8ecb44 | ||
|
|
e6fcfaf6f6 | ||
|
|
f85b61860e | ||
|
|
dea9b1604f | ||
|
|
2a45647293 | ||
|
|
063e02b3a8 | ||
|
|
8e9b8adac9 | ||
|
|
eb52eba944 | ||
|
|
63c92f8e6c | ||
|
|
2d3851f409 | ||
|
|
035fcc0362 | ||
|
|
9d1f70229b | ||
|
|
2ea70e30c4 | ||
|
|
5d30a1301c | ||
|
|
61a5422559 | ||
|
|
3c5874a37a | ||
|
|
47720bdacb | ||
|
|
0d559d6031 | ||
|
|
28542e907d | ||
|
|
5aec7e5e24 | ||
|
|
9a36fba438 | ||
|
|
85e6d00f2f | ||
|
|
5ca926c255 | ||
|
|
d15ef08576 | ||
|
|
4f11a1e6e2 | ||
|
|
b739e4816c | ||
|
|
d93279bceb | ||
|
|
e286dc94a7 | ||
|
|
5a32195091 | ||
|
|
7495eba74f | ||
|
|
bb3b7fee48 | ||
|
|
e2af0dc493 | ||
|
|
535c0e127d | ||
|
|
2f70e92df8 | ||
|
|
73746ad885 | ||
|
|
a6b3895756 | ||
|
|
72012c19e6 | ||
|
|
a440a59435 | ||
|
|
6fcc9de3b1 | ||
|
|
f5a621174a | ||
|
|
76016fba71 | ||
|
|
c9af3fcad1 | ||
|
|
d3c79538e0 | ||
|
|
9127bdb66a | ||
|
|
45a46d7337 | ||
|
|
f5c7cffb82 | ||
|
|
e52539bed6 | ||
|
|
9bd7bbf274 | ||
|
|
2e6c26c982 | ||
|
|
cbc1fea680 | ||
|
|
a1d89711b0 | ||
|
|
7b985fcb6e | ||
|
|
a783bd69fa | ||
|
|
35f11679b1 | ||
|
|
063788c8af | ||
|
|
4be73f2d52 | ||
|
|
bd53884e23 | ||
|
|
4eca6ca5b1 | ||
|
|
93ed1c7171 | ||
|
|
97a4dccc42 | ||
|
|
0ef6733d67 | ||
|
|
80538d6344 | ||
|
|
8e0b5b9413 | ||
|
|
14679921d0 |
4
.github/actions/setup-caches/action.yaml
vendored
4
.github/actions/setup-caches/action.yaml
vendored
@@ -9,11 +9,11 @@ inputs:
|
|||||||
runs:
|
runs:
|
||||||
using: composite
|
using: composite
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
||||||
with:
|
with:
|
||||||
path: ~/go/pkg/mod
|
path: ~/go/pkg/mod
|
||||||
key: ${{ runner.os }}-go-pkg-mod-${{ hashFiles('**/go.sum') }}-${{ hashFiles('Makefile') }}
|
key: ${{ runner.os }}-go-pkg-mod-${{ hashFiles('**/go.sum') }}-${{ hashFiles('Makefile') }}
|
||||||
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
||||||
if: ${{ inputs.build-cache-key }}
|
if: ${{ inputs.build-cache-key }}
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/go-build
|
path: ~/.cache/go-build
|
||||||
|
|||||||
6
.github/configs/lintconf.yaml
vendored
6
.github/configs/lintconf.yaml
vendored
@@ -6,6 +6,12 @@ ignore:
|
|||||||
rules:
|
rules:
|
||||||
truthy:
|
truthy:
|
||||||
level: warning
|
level: warning
|
||||||
|
allowed-values:
|
||||||
|
- "true"
|
||||||
|
- "false"
|
||||||
|
- "on"
|
||||||
|
- "off"
|
||||||
|
|
||||||
check-keys: false
|
check-keys: false
|
||||||
braces:
|
braces:
|
||||||
min-spaces-inside: 0
|
min-spaces-inside: 0
|
||||||
|
|||||||
8
.github/maintainers.yaml
vendored
8
.github/maintainers.yaml
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
maintainers:
|
||||||
- name: Adriano Pezzuto
|
- name: Adriano Pezzuto
|
||||||
github: https://github.com/bsctl
|
github: https://github.com/bsctl
|
||||||
company: Clastix
|
company: Clastix
|
||||||
@@ -21,9 +22,16 @@
|
|||||||
company: Peak Scale
|
company: Peak Scale
|
||||||
projects:
|
projects:
|
||||||
- https://github.com/projectcapsule/capsule
|
- https://github.com/projectcapsule/capsule
|
||||||
|
- https://github.com/projectcapsule/capsule-proxy
|
||||||
- name: Massimiliano Giovagnoli
|
- name: Massimiliano Giovagnoli
|
||||||
github: https://github.com/maxgio92
|
github: https://github.com/maxgio92
|
||||||
company: Proximus
|
company: Proximus
|
||||||
projects:
|
projects:
|
||||||
- https://github.com/projectcapsule/capsule
|
- https://github.com/projectcapsule/capsule
|
||||||
- https://github.com/projectcapsule/capsule-proxy
|
- https://github.com/projectcapsule/capsule-proxy
|
||||||
|
- name: Hristo Hristov
|
||||||
|
github: https://github.com/Svarrogh1337
|
||||||
|
company: Vaerolabs
|
||||||
|
projects:
|
||||||
|
- https://github.com/projectcapsule/capsule
|
||||||
|
- https://github.com/projectcapsule/capsule-proxy
|
||||||
|
|||||||
4
.github/workflows/check-actions.yml
vendored
4
.github/workflows/check-actions.yml
vendored
@@ -15,9 +15,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
- name: Ensure SHA pinned actions
|
- name: Ensure SHA pinned actions
|
||||||
uses: zgosalvez/github-actions-ensure-sha-pinned-actions@6eb1abde32fed00453b0d03497f4ba4fecba146d # v3.0.21
|
uses: zgosalvez/github-actions-ensure-sha-pinned-actions@d5d20e15f2736816ee0e001ba8b24b54d9ffcff4 # v5.0.0
|
||||||
with:
|
with:
|
||||||
# slsa-github-generator requires using a semver tag for reusable workflows.
|
# slsa-github-generator requires using a semver tag for reusable workflows.
|
||||||
# See: https://github.com/slsa-framework/slsa-github-generator#referencing-slsa-builders-and-generators
|
# See: https://github.com/slsa-framework/slsa-github-generator#referencing-slsa-builders-and-generators
|
||||||
|
|||||||
2
.github/workflows/check-commit.yml
vendored
2
.github/workflows/check-commit.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
commit_lint:
|
commit_lint:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: wagoid/commitlint-github-action@b948419dd99f3fd78a6548d48f94e3df7f6bf3ed # v6.2.1
|
- uses: wagoid/commitlint-github-action@b948419dd99f3fd78a6548d48f94e3df7f6bf3ed # v6.2.1
|
||||||
|
|||||||
2
.github/workflows/check-pr.yml
vendored
2
.github/workflows/check-pr.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
name: Validate PR title
|
name: Validate PR title
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: amannn/action-semantic-pull-request@40166f00814508ec3201fc8595b393d451c8cd80
|
- uses: amannn/action-semantic-pull-request@ac7e3fc035c47465748bbcb1a822c1583cf79bbc
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
|
|||||||
20
.github/workflows/coverage.yml
vendored
20
.github/workflows/coverage.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
|||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout Code"
|
- name: "Checkout Code"
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
- name: Check secret
|
- name: Check secret
|
||||||
id: checksecret
|
id: checksecret
|
||||||
uses: ./.github/actions/exists
|
uses: ./.github/actions/exists
|
||||||
@@ -27,12 +27,12 @@ jobs:
|
|||||||
value: ${{ secrets.FOSSA_API_KEY }}
|
value: ${{ secrets.FOSSA_API_KEY }}
|
||||||
- name: "Run FOSSA Scan"
|
- name: "Run FOSSA Scan"
|
||||||
if: steps.checksecret.outputs.result == 'true'
|
if: steps.checksecret.outputs.result == 'true'
|
||||||
uses: fossas/fossa-action@93a52ecf7c3ac7eb40f5de77fd69b1a19524de94 # v1.5.0
|
uses: fossas/fossa-action@3ebcea1862c6ffbd5cf1b4d0bd6b3fe7bd6f2cac # v1.7.0
|
||||||
with:
|
with:
|
||||||
api-key: ${{ secrets.FOSSA_API_KEY }}
|
api-key: ${{ secrets.FOSSA_API_KEY }}
|
||||||
- name: "Run FOSSA Test"
|
- name: "Run FOSSA Test"
|
||||||
if: steps.checksecret.outputs.result == 'true'
|
if: steps.checksecret.outputs.result == 'true'
|
||||||
uses: fossas/fossa-action@93a52ecf7c3ac7eb40f5de77fd69b1a19524de94 # v1.5.0
|
uses: fossas/fossa-action@3ebcea1862c6ffbd5cf1b4d0bd6b3fe7bd6f2cac # v1.7.0
|
||||||
with:
|
with:
|
||||||
api-key: ${{ secrets.FOSSA_API_KEY }}
|
api-key: ${{ secrets.FOSSA_API_KEY }}
|
||||||
run-tests: true
|
run-tests: true
|
||||||
@@ -47,16 +47,16 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Source
|
- name: Checkout Source
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
- uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
|
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
||||||
with:
|
with:
|
||||||
go-version-file: 'go.mod'
|
go-version-file: 'go.mod'
|
||||||
- name: Run Gosec Security Scanner
|
- name: Run Gosec Security Scanner
|
||||||
uses: securego/gosec@e0cca6fe95306b7e7790d6f1bf6a7bec6d622459 # v2.22.0
|
uses: securego/gosec@424fc4cd9c82ea0fd6bee9cd49c2db2c3cc0c93f # v2.22.11
|
||||||
with:
|
with:
|
||||||
args: '-no-fail -fmt sarif -out gosec.sarif ./...'
|
args: '-no-fail -fmt sarif -out gosec.sarif ./...'
|
||||||
- name: Upload SARIF file
|
- name: Upload SARIF file
|
||||||
uses: github/codeql-action/upload-sarif@0a35e8f6866a39b001e5f7ad1d0daf9836786896
|
uses: github/codeql-action/upload-sarif@0ec47d036c68ae0cf94c629009b1029407111281
|
||||||
with:
|
with:
|
||||||
sarif_file: gosec.sarif
|
sarif_file: gosec.sarif
|
||||||
unit_tests:
|
unit_tests:
|
||||||
@@ -64,8 +64,8 @@ jobs:
|
|||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
- uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
|
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
||||||
with:
|
with:
|
||||||
go-version-file: 'go.mod'
|
go-version-file: 'go.mod'
|
||||||
- name: Unit Test
|
- name: Unit Test
|
||||||
@@ -77,7 +77,7 @@ jobs:
|
|||||||
value: ${{ secrets.CODECOV_TOKEN }}
|
value: ${{ secrets.CODECOV_TOKEN }}
|
||||||
- name: Upload Report to Codecov
|
- name: Upload Report to Codecov
|
||||||
if: ${{ steps.checksecret.outputs.result == 'true' }}
|
if: ${{ steps.checksecret.outputs.result == 'true' }}
|
||||||
uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1
|
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
slug: projectcapsule/capsule
|
slug: projectcapsule/capsule
|
||||||
|
|||||||
6
.github/workflows/docker-build.yml
vendored
6
.github/workflows/docker-build.yml
vendored
@@ -24,11 +24,11 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
- name: ko build
|
- name: ko build
|
||||||
run: VERSION=${{ github.sha }} make ko-build-all
|
run: VERSION=${{ github.sha }} make ko-build-all
|
||||||
- name: Trivy Scan Image
|
- name: Trivy Scan Image
|
||||||
uses: aquasecurity/trivy-action@18f2510ee396bbf400402947b394f2dd8c87dbb0 # v0.29.0
|
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1
|
||||||
with:
|
with:
|
||||||
scan-type: 'fs'
|
scan-type: 'fs'
|
||||||
ignore-unfixed: true
|
ignore-unfixed: true
|
||||||
@@ -40,6 +40,6 @@ jobs:
|
|||||||
# See: https://github.com/aquasecurity/trivy-action/issues/389#issuecomment-2385416577
|
# See: https://github.com/aquasecurity/trivy-action/issues/389#issuecomment-2385416577
|
||||||
TRIVY_DB_REPOSITORY: 'public.ecr.aws/aquasecurity/trivy-db:2'
|
TRIVY_DB_REPOSITORY: 'public.ecr.aws/aquasecurity/trivy-db:2'
|
||||||
- name: Upload Trivy scan results to GitHub Security tab
|
- name: Upload Trivy scan results to GitHub Security tab
|
||||||
uses: github/codeql-action/upload-sarif@0a35e8f6866a39b001e5f7ad1d0daf9836786896
|
uses: github/codeql-action/upload-sarif@0ec47d036c68ae0cf94c629009b1029407111281
|
||||||
with:
|
with:
|
||||||
sarif_file: 'trivy-results.sarif'
|
sarif_file: 'trivy-results.sarif'
|
||||||
|
|||||||
10
.github/workflows/docker-publish.yml
vendored
10
.github/workflows/docker-publish.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
|||||||
capsule-digest: ${{ steps.publish-capsule.outputs.digest }}
|
capsule-digest: ${{ steps.publish-capsule.outputs.digest }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
- name: Setup caches
|
- name: Setup caches
|
||||||
uses: ./.github/actions/setup-caches
|
uses: ./.github/actions/setup-caches
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
@@ -28,7 +28,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
build-cache-key: publish-images
|
build-cache-key: publish-images
|
||||||
- name: Run Trivy vulnerability (Repo)
|
- name: Run Trivy vulnerability (Repo)
|
||||||
uses: aquasecurity/trivy-action@18f2510ee396bbf400402947b394f2dd8c87dbb0 # v0.29.0
|
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1
|
||||||
with:
|
with:
|
||||||
scan-type: 'fs'
|
scan-type: 'fs'
|
||||||
ignore-unfixed: true
|
ignore-unfixed: true
|
||||||
@@ -36,7 +36,7 @@ jobs:
|
|||||||
output: 'trivy-results.sarif'
|
output: 'trivy-results.sarif'
|
||||||
severity: 'CRITICAL,HIGH'
|
severity: 'CRITICAL,HIGH'
|
||||||
- name: Install Cosign
|
- name: Install Cosign
|
||||||
uses: sigstore/cosign-installer@c56c2d3e59e4281cc41dea2217323ba5694b171e # v3.8.0
|
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
|
||||||
- name: Publish Capsule
|
- name: Publish Capsule
|
||||||
id: publish-capsule
|
id: publish-capsule
|
||||||
uses: peak-scale/github-actions/make-ko-publish@a441cca016861c546ab7e065277e40ce41a3eb84 # v0.2.0
|
uses: peak-scale/github-actions/make-ko-publish@a441cca016861c546ab7e065277e40ce41a3eb84 # v0.2.0
|
||||||
@@ -51,7 +51,7 @@ jobs:
|
|||||||
sbom-name: capsule
|
sbom-name: capsule
|
||||||
sbom-repository: ghcr.io/${{ github.repository_owner }}/capsule
|
sbom-repository: ghcr.io/${{ github.repository_owner }}/capsule
|
||||||
signature-repository: ghcr.io/${{ github.repository_owner }}/capsule
|
signature-repository: ghcr.io/${{ github.repository_owner }}/capsule
|
||||||
main-path: ./
|
main-path: ./cmd/
|
||||||
env:
|
env:
|
||||||
REPOSITORY: ${{ github.repository }}
|
REPOSITORY: ${{ github.repository }}
|
||||||
generate-capsule-provenance:
|
generate-capsule-provenance:
|
||||||
@@ -60,7 +60,7 @@ jobs:
|
|||||||
id-token: write # To sign the provenance.
|
id-token: write # To sign the provenance.
|
||||||
packages: write # To upload assets to release.
|
packages: write # To upload assets to release.
|
||||||
actions: read # To read the workflow path.
|
actions: read # To read the workflow path.
|
||||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0
|
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
|
||||||
with:
|
with:
|
||||||
image: ghcr.io/${{ github.repository_owner }}/capsule
|
image: ghcr.io/${{ github.repository_owner }}/capsule
|
||||||
digest: "${{ needs.publish-images.outputs.capsule-digest }}"
|
digest: "${{ needs.publish-images.outputs.capsule-digest }}"
|
||||||
|
|||||||
52
.github/workflows/e2e.yml
vendored
52
.github/workflows/e2e.yml
vendored
@@ -9,6 +9,7 @@ on:
|
|||||||
- '.github/workflows/e2e.yml'
|
- '.github/workflows/e2e.yml'
|
||||||
- 'api/**'
|
- 'api/**'
|
||||||
- 'controllers/**'
|
- 'controllers/**'
|
||||||
|
- 'internal/**'
|
||||||
- 'pkg/**'
|
- 'pkg/**'
|
||||||
- 'e2e/*'
|
- 'e2e/*'
|
||||||
- 'Dockerfile'
|
- 'Dockerfile'
|
||||||
@@ -22,26 +23,45 @@ concurrency:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
e2e:
|
e2e:
|
||||||
name: E2E Testing
|
name: E2E Testing (CE)
|
||||||
runs-on: ubuntu-latest
|
runs-on:
|
||||||
|
labels: ubuntu-latest-8-cores
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
|
|
||||||
|
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
||||||
with:
|
with:
|
||||||
go-version-file: 'go.mod'
|
go-version-file: 'go.mod'
|
||||||
- uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4
|
|
||||||
|
- uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4
|
||||||
|
|
||||||
|
- name: e2e
|
||||||
|
run: sudo make e2e
|
||||||
|
run-e2e:
|
||||||
|
name: E2E Testing
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
k8s-version:
|
||||||
|
- 'v1.31.0'
|
||||||
|
- 'v1.32.0'
|
||||||
|
- 'v1.33.0'
|
||||||
|
- 'v1.34.0'
|
||||||
|
runs-on:
|
||||||
|
labels: ubuntu-latest-8-cores
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
with:
|
with:
|
||||||
version: v3.14.2
|
repository: ${{ github.event.client_payload.repo }}
|
||||||
- name: unit tracing
|
ref: ${{ github.event.client_payload.sha }}
|
||||||
run: sudo make trace-unit
|
|
||||||
- name: e2e tracing
|
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
||||||
run: sudo make trace-e2e
|
|
||||||
- name: build seccomp profile
|
|
||||||
run: make seccomp
|
|
||||||
- name: upload artifact
|
|
||||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
|
||||||
with:
|
with:
|
||||||
name: capsule-seccomp
|
go-version-file: 'go.mod'
|
||||||
path: capsule-seccomp.json
|
|
||||||
|
- uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4
|
||||||
|
|
||||||
|
- name: e2e (Enterprise)
|
||||||
|
run: sudo KUBERNETES_SUPPORTED_VERSION=${{ matrix.k8s-version }} make e2e
|
||||||
|
|||||||
8
.github/workflows/helm-publish.yml
vendored
8
.github/workflows/helm-publish.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
if: github.repository_owner == 'projectcapsule'
|
if: github.repository_owner == 'projectcapsule'
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
- name: "Extract Version"
|
- name: "Extract Version"
|
||||||
id: extract_version
|
id: extract_version
|
||||||
run: |
|
run: |
|
||||||
@@ -45,8 +45,8 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
chart-digest: ${{ steps.helm_publish.outputs.digest }}
|
chart-digest: ${{ steps.helm_publish.outputs.digest }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
- uses: sigstore/cosign-installer@c56c2d3e59e4281cc41dea2217323ba5694b171e # v3.8.0
|
- uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
|
||||||
- name: "Extract Version"
|
- name: "Extract Version"
|
||||||
id: extract_version
|
id: extract_version
|
||||||
run: |
|
run: |
|
||||||
@@ -73,7 +73,7 @@ jobs:
|
|||||||
id-token: write # To sign the provenance.
|
id-token: write # To sign the provenance.
|
||||||
packages: write # To upload assets to release.
|
packages: write # To upload assets to release.
|
||||||
actions: read # To read the workflow path.
|
actions: read # To read the workflow path.
|
||||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0
|
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
|
||||||
with:
|
with:
|
||||||
image: ghcr.io/${{ github.repository_owner }}/charts/capsule
|
image: ghcr.io/${{ github.repository_owner }}/charts/capsule
|
||||||
digest: "${{ needs.publish-helm-oci.outputs.chart-digest }}"
|
digest: "${{ needs.publish-helm-oci.outputs.chart-digest }}"
|
||||||
|
|||||||
6
.github/workflows/helm-test.yml
vendored
6
.github/workflows/helm-test.yml
vendored
@@ -23,17 +23,17 @@ jobs:
|
|||||||
options: --user root
|
options: --user root
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
- name: Run ah lint
|
- name: Run ah lint
|
||||||
working-directory: ./charts/
|
working-directory: ./charts/
|
||||||
run: ah lint
|
run: ah lint
|
||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4
|
- uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4
|
||||||
- name: Linting Chart
|
- name: Linting Chart
|
||||||
run: helm lint ./charts/capsule
|
run: helm lint ./charts/capsule
|
||||||
|
|
||||||
|
|||||||
11
.github/workflows/lint.yml
vendored
11
.github/workflows/lint.yml
vendored
@@ -15,14 +15,15 @@ jobs:
|
|||||||
name: diff
|
name: diff
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
|
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
||||||
with:
|
with:
|
||||||
go-version-file: 'go.mod'
|
go-version-file: 'go.mod'
|
||||||
- name: Generate manifests
|
- name: Generate manifests
|
||||||
run: |
|
run: |
|
||||||
|
make generate
|
||||||
make manifests
|
make manifests
|
||||||
if [[ $(git diff --stat) != '' ]]; then
|
if [[ $(git diff --stat) != '' ]]; then
|
||||||
echo -e '\033[0;31mManifests outdated! (Run make manifests locally and commit)\033[0m ❌'
|
echo -e '\033[0;31mManifests outdated! (Run make manifests locally and commit)\033[0m ❌'
|
||||||
@@ -35,7 +36,7 @@ jobs:
|
|||||||
name: yamllint
|
name: yamllint
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
- name: Install yamllint
|
- name: Install yamllint
|
||||||
run: pip install yamllint
|
run: pip install yamllint
|
||||||
- name: Lint YAML files
|
- name: Lint YAML files
|
||||||
@@ -44,8 +45,8 @@ jobs:
|
|||||||
name: lint
|
name: lint
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
- uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
|
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
||||||
with:
|
with:
|
||||||
go-version-file: 'go.mod'
|
go-version-file: 'go.mod'
|
||||||
- name: Run golangci-lint
|
- name: Run golangci-lint
|
||||||
|
|||||||
49
.github/workflows/releaser.yml
vendored
49
.github/workflows/releaser.yml
vendored
@@ -11,52 +11,18 @@ concurrency:
|
|||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
seccomp-generation:
|
|
||||||
name: Seccomp Generation
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
# differently from the e2e workflow
|
|
||||||
# we don't need all the versions of kubernetes
|
|
||||||
# to generate the seccomp profile.
|
|
||||||
k8s-version:
|
|
||||||
- "v1.30.0"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
|
|
||||||
with:
|
|
||||||
go-version-file: 'go.mod'
|
|
||||||
- uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4
|
|
||||||
with:
|
|
||||||
version: v3.14.2
|
|
||||||
- name: unit tracing
|
|
||||||
run: sudo make trace-unit
|
|
||||||
- name: e2e tracing
|
|
||||||
run: sudo KIND_K8S_VERSION=${{ matrix.k8s-version }} make trace-e2e
|
|
||||||
- name: build seccomp profile
|
|
||||||
run: make seccomp
|
|
||||||
- name: upload artifact
|
|
||||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
|
||||||
with:
|
|
||||||
name: capsule-seccomp
|
|
||||||
path: capsule-seccomp.json
|
|
||||||
|
|
||||||
create-release:
|
create-release:
|
||||||
needs: seccomp-generation
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
id-token: write
|
id-token: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
|
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
||||||
with:
|
with:
|
||||||
go-version-file: 'go.mod'
|
go-version-file: 'go.mod'
|
||||||
- name: Setup caches
|
- name: Setup caches
|
||||||
@@ -64,16 +30,11 @@ jobs:
|
|||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
- uses: creekorful/goreportcard-action@1f35ced8cdac2cba28c9a2f2288a16aacfd507f9 # v1.0
|
- uses: creekorful/goreportcard-action@1f35ced8cdac2cba28c9a2f2288a16aacfd507f9 # v1.0
|
||||||
- uses: anchore/sbom-action/download-syft@79202aee38a39bd2039be442e58d731b63baf740
|
- uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610
|
||||||
- name: Install Cosign
|
- name: Install Cosign
|
||||||
uses: sigstore/cosign-installer@c56c2d3e59e4281cc41dea2217323ba5694b171e # v3.8.0
|
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
|
||||||
- name: download artifact
|
|
||||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
|
||||||
with:
|
|
||||||
name: capsule-seccomp
|
|
||||||
path: ./capsule-seccomp.json
|
|
||||||
- name: Run GoReleaser
|
- name: Run GoReleaser
|
||||||
uses: goreleaser/goreleaser-action@9ed2f89a662bf1735a48bc8557fd212fa902bebf # v6.1.0
|
uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
args: release --clean --timeout 90m
|
args: release --clean --timeout 90m
|
||||||
|
|||||||
8
.github/workflows/scorecard.yml
vendored
8
.github/workflows/scorecard.yml
vendored
@@ -20,23 +20,23 @@ jobs:
|
|||||||
id-token: write
|
id-token: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Run analysis
|
- name: Run analysis
|
||||||
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
|
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
|
||||||
with:
|
with:
|
||||||
results_file: results.sarif
|
results_file: results.sarif
|
||||||
results_format: sarif
|
results_format: sarif
|
||||||
repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}
|
repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}
|
||||||
publish_results: true
|
publish_results: true
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||||
with:
|
with:
|
||||||
name: SARIF file
|
name: SARIF file
|
||||||
path: results.sarif
|
path: results.sarif
|
||||||
retention-days: 5
|
retention-days: 5
|
||||||
- name: Upload to code-scanning
|
- name: Upload to code-scanning
|
||||||
uses: github/codeql-action/upload-sarif@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9
|
uses: github/codeql-action/upload-sarif@6bc82e05fd0ea64601dd4b465378bbcf57de0314 # v4.32.1
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
sarif_file: results.sarif
|
||||||
|
|||||||
26
.github/workflows/stale.yml
vendored
Normal file
26
.github/workflows/stale.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: Stale-Bot
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *' # Run every day at midnight
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: write
|
||||||
|
contents: write # only for delete-branch option
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
steps:
|
||||||
|
- name: Close stale pull requests
|
||||||
|
uses: actions/stale@db5d06a4c82d5e94513c09c406638111df61f63e
|
||||||
|
with:
|
||||||
|
stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 30 days.'
|
||||||
|
stale-pr-message: 'This pull request has been marked as stale because it has been inactive for more than 30 days. Please update this pull request or it will be automatically closed in 30 days.'
|
||||||
|
days-before-issue-stale: 60
|
||||||
|
days-before-pr-stale: 30
|
||||||
|
days-before-issue-close: 30
|
||||||
|
days-before-pr-close: 30
|
||||||
|
stale-pr-label: stale
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -7,6 +7,8 @@
|
|||||||
*.dylib
|
*.dylib
|
||||||
bin
|
bin
|
||||||
dist/
|
dist/
|
||||||
|
config/
|
||||||
|
builds/
|
||||||
|
|
||||||
# Test binary, build with `go test -c`
|
# Test binary, build with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
|
|||||||
91
.golangci.yaml
Normal file
91
.golangci.yaml
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
version: "2"
|
||||||
|
run:
|
||||||
|
tests: false
|
||||||
|
allow-parallel-runners: true
|
||||||
|
linters:
|
||||||
|
default: all
|
||||||
|
disable:
|
||||||
|
- godoclint
|
||||||
|
- depguard
|
||||||
|
- err113
|
||||||
|
- exhaustruct
|
||||||
|
- funlen
|
||||||
|
- gochecknoglobals
|
||||||
|
- gochecknoinits
|
||||||
|
- ireturn
|
||||||
|
- lll
|
||||||
|
- mnd
|
||||||
|
- nilnil
|
||||||
|
- nonamedreturns
|
||||||
|
- paralleltest
|
||||||
|
- perfsprint
|
||||||
|
- recvcheck
|
||||||
|
- testpackage
|
||||||
|
- unparam
|
||||||
|
- varnamelen
|
||||||
|
- wrapcheck
|
||||||
|
- interfacebloat
|
||||||
|
- noinlineerr
|
||||||
|
- revive
|
||||||
|
settings:
|
||||||
|
cyclop:
|
||||||
|
max-complexity: 27
|
||||||
|
dupl:
|
||||||
|
threshold: 100
|
||||||
|
gocognit:
|
||||||
|
min-complexity: 50
|
||||||
|
goconst:
|
||||||
|
min-len: 2
|
||||||
|
min-occurrences: 2
|
||||||
|
goheader:
|
||||||
|
template: |-
|
||||||
|
Copyright 2020-2026 Project Capsule Authors
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
inamedparam:
|
||||||
|
skip-single-param: true
|
||||||
|
nakedret:
|
||||||
|
max-func-lines: 50
|
||||||
|
exclusions:
|
||||||
|
generated: lax
|
||||||
|
presets:
|
||||||
|
- comments
|
||||||
|
- common-false-positives
|
||||||
|
- legacy
|
||||||
|
- std-error-handling
|
||||||
|
paths:
|
||||||
|
- zz_.*\.go$
|
||||||
|
- .+\.generated.go
|
||||||
|
- .+_test.go
|
||||||
|
- .+_test_.+.go
|
||||||
|
- third_party$
|
||||||
|
- builtin$
|
||||||
|
- examples$
|
||||||
|
rules:
|
||||||
|
- path: pkg/meta/
|
||||||
|
linters:
|
||||||
|
- dupl
|
||||||
|
formatters:
|
||||||
|
enable:
|
||||||
|
- gci
|
||||||
|
- gofmt
|
||||||
|
- gofumpt
|
||||||
|
- goimports
|
||||||
|
settings:
|
||||||
|
gci:
|
||||||
|
sections:
|
||||||
|
- standard
|
||||||
|
- default
|
||||||
|
- prefix(github.com/projectcapsule/capsule)
|
||||||
|
gofumpt:
|
||||||
|
module-path: github.com/projectcapsule/capsule
|
||||||
|
extra-rules: false
|
||||||
|
exclusions:
|
||||||
|
generated: lax
|
||||||
|
paths:
|
||||||
|
- zz_.*\.go$
|
||||||
|
- .+\.generated.go
|
||||||
|
- .+_test.go
|
||||||
|
- .+_test_.+.go
|
||||||
|
- third_party$
|
||||||
|
- builtin$
|
||||||
|
- examples$
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
linters-settings:
|
|
||||||
dupl:
|
|
||||||
threshold: 100
|
|
||||||
goconst:
|
|
||||||
min-len: 2
|
|
||||||
min-occurrences: 2
|
|
||||||
cyclop:
|
|
||||||
max-complexity: 27
|
|
||||||
gocognit:
|
|
||||||
min-complexity: 50
|
|
||||||
gci:
|
|
||||||
sections:
|
|
||||||
- standard
|
|
||||||
- default
|
|
||||||
- prefix(github.com/projectcapsule/capsule)
|
|
||||||
goheader:
|
|
||||||
template: |-
|
|
||||||
Copyright 2020-2023 Project Capsule Authors.
|
|
||||||
SPDX-License-Identifier: Apache-2.0
|
|
||||||
gofumpt:
|
|
||||||
module-path: github.com/projectcapsule/capsule
|
|
||||||
extra-rules: false
|
|
||||||
inamedparam:
|
|
||||||
# Skips check for interface methods with only a single parameter.
|
|
||||||
# Default: false
|
|
||||||
skip-single-param: true
|
|
||||||
nakedret:
|
|
||||||
# Make an issue if func has more lines of code than this setting, and it has naked returns.
|
|
||||||
max-func-lines: 50
|
|
||||||
linters:
|
|
||||||
enable-all: true
|
|
||||||
disable:
|
|
||||||
- err113
|
|
||||||
- depguard
|
|
||||||
- perfsprint
|
|
||||||
- funlen
|
|
||||||
- gochecknoinits
|
|
||||||
- lll
|
|
||||||
- gochecknoglobals
|
|
||||||
- mnd
|
|
||||||
- nilnil
|
|
||||||
- recvcheck
|
|
||||||
- unparam
|
|
||||||
- paralleltest
|
|
||||||
- ireturn
|
|
||||||
- testpackage
|
|
||||||
- varnamelen
|
|
||||||
- wrapcheck
|
|
||||||
- exhaustruct
|
|
||||||
- nonamedreturns
|
|
||||||
issues:
|
|
||||||
exclude-files:
|
|
||||||
- "zz_.*\\.go$"
|
|
||||||
- ".+\\.generated.go"
|
|
||||||
- ".+_test.go"
|
|
||||||
- ".+_test_.+.go"
|
|
||||||
run:
|
|
||||||
timeout: 3m
|
|
||||||
allow-parallel-runners: true
|
|
||||||
tests: false
|
|
||||||
@@ -8,7 +8,8 @@ before:
|
|||||||
gomod:
|
gomod:
|
||||||
proxy: false
|
proxy: false
|
||||||
builds:
|
builds:
|
||||||
- main: .
|
- id: "{{ .ProjectName }}"
|
||||||
|
main: ./cmd/
|
||||||
binary: "{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}"
|
binary: "{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}"
|
||||||
env:
|
env:
|
||||||
- CGO_ENABLED=0
|
- CGO_ENABLED=0
|
||||||
@@ -28,11 +29,33 @@ builds:
|
|||||||
-X main.GitDirty={{ .Date }}
|
-X main.GitDirty={{ .Date }}
|
||||||
-X main.BuildTime={{ .Date }}
|
-X main.BuildTime={{ .Date }}
|
||||||
-X main.GitRepo={{ .ProjectName }}
|
-X main.GitRepo={{ .ProjectName }}
|
||||||
|
# - id: "{{ .ProjectName }}-wasm"
|
||||||
|
# main: ./cmd/
|
||||||
|
# binary: "{{ .ProjectName }}.wasm"
|
||||||
|
# env:
|
||||||
|
# - CGO_ENABLED=0
|
||||||
|
# goos:
|
||||||
|
# - js
|
||||||
|
# goarch:
|
||||||
|
# - wasm
|
||||||
|
# flags:
|
||||||
|
# - -trimpath
|
||||||
|
# mod_timestamp: '{{ .CommitTimestamp }}'
|
||||||
|
# ldflags:
|
||||||
|
# - >-
|
||||||
|
# -X main.Version={{ .Tag }}
|
||||||
|
# -X main.GitCommit={{ .Commit }}
|
||||||
|
# -X main.GitTag={{ .Tag }}
|
||||||
|
# -X main.GitDirty={{ .Date }}
|
||||||
|
# -X main.BuildTime={{ .Date }}
|
||||||
|
# -X main.GitRepo={{ .ProjectName }}
|
||||||
release:
|
release:
|
||||||
prerelease: auto
|
prerelease: auto
|
||||||
footer: |
|
footer: |
|
||||||
**Full Changelog**: https://github.com/projectcapsule/{{ .ProjectName }}/compare/{{ .PreviousTag }}...{{ .Tag }}
|
**Full Changelog**: https://github.com/projectcapsule/{{ .ProjectName }}/compare/{{ .PreviousTag }}...{{ .Tag }}
|
||||||
|
|
||||||
|
[Check out what's new in this release](https://projectcapsule.dev/docs/whats-new/)
|
||||||
|
|
||||||
**Docker Images**
|
**Docker Images**
|
||||||
- `ghcr.io/projectcapsule/{{ .ProjectName }}:{{ .Version }}`
|
- `ghcr.io/projectcapsule/{{ .ProjectName }}:{{ .Version }}`
|
||||||
- `ghcr.io/projectcapsule/{{ .ProjectName }}:latest`
|
- `ghcr.io/projectcapsule/{{ .ProjectName }}:latest`
|
||||||
@@ -44,20 +67,18 @@ release:
|
|||||||
|
|
||||||
[Review the Major Changes section first before upgrading to a new version](https://artifacthub.io/packages/helm/projectcapsule/capsule/{{ .Version }}#major-changes)
|
[Review the Major Changes section first before upgrading to a new version](https://artifacthub.io/packages/helm/projectcapsule/capsule/{{ .Version }}#major-changes)
|
||||||
|
|
||||||
**Kubernetes compatibility**
|
> [!IMPORTANT]
|
||||||
|
> **Kubernetes compatibility**
|
||||||
[!IMPORTANT]
|
>
|
||||||
Note that the Capsule project offers support only for the latest minor version of Kubernetes.
|
> Note that the Capsule project offers support only for the latest minor version of Kubernetes.
|
||||||
Backwards compatibility with older versions of Kubernetes and OpenShift is [offered by vendors](https://projectcapsule.dev/support/).
|
> Backwards compatibility with older versions of Kubernetes and OpenShift is [offered by vendors](https://projectcapsule.dev/support/).
|
||||||
|
>
|
||||||
| Kubernetes version | Minimum required |
|
> | Kubernetes version | Minimum required |
|
||||||
|--------------------|------------------|
|
> |--------------------|------------------|
|
||||||
| `v1.31` | `>= 1.31.0` |
|
> | `v1.35` | `>= 1.35.0` |
|
||||||
|
|
||||||
|
|
||||||
Thanks to all the contributors! 🚀 🦄
|
Thanks to all the contributors! 🚀 🦄
|
||||||
extra_files:
|
|
||||||
- glob: ./capsule-seccomp.json
|
|
||||||
checksum:
|
checksum:
|
||||||
name_template: 'checksums.txt'
|
name_template: 'checksums.txt'
|
||||||
changelog:
|
changelog:
|
||||||
@@ -75,24 +96,25 @@ changelog:
|
|||||||
groups:
|
groups:
|
||||||
# https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional
|
# https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional
|
||||||
- title: '🛠 Dependency updates'
|
- title: '🛠 Dependency updates'
|
||||||
regexp: '^.*?(feat|fix)\(deps\)!?:.+$'
|
regexp: '^fix\(deps\):|^feat\(deps\):'
|
||||||
order: 300
|
order: 300
|
||||||
- title: '✨ New Features'
|
- title: '✨ New Features'
|
||||||
regexp: '^.*?feat(\([[:word:]]+\))??!?:.+$'
|
regexp: '^feat(\([^)]*\))?:'
|
||||||
order: 100
|
order: 100
|
||||||
- title: '🐛 Bug fixes'
|
- title: '🐛 Bug fixes'
|
||||||
regexp: '^.*?fix(\([[:word:]]+\))??!?:.+$'
|
regexp: '^fix(\([^)]*\))?:'
|
||||||
order: 200
|
order: 200
|
||||||
- title: '📖 Documentation updates'
|
- title: '📖 Documentation updates'
|
||||||
regexp: ^.*?docs(\([[:word:]]+\))??!?:.+$
|
regexp: '^docs(\([^)]*\))?:'
|
||||||
order: 400
|
order: 400
|
||||||
- title: '🛡️ Security updates'
|
- title: '🛡️ Security updates'
|
||||||
regexp: ^.*?(sec)(\([[:word:]]+\))??!?:.+$
|
regexp: '^sec(\([^)]*\))?:'
|
||||||
order: 500
|
order: 500
|
||||||
- title: '🚀 Build process updates'
|
- title: '🚀 Build process updates'
|
||||||
regexp: ^.*?(build|ci)(\([[:word:]]+\))??!?:.+$
|
regexp: '^(build|ci)(\([^)]*\))?:'
|
||||||
order: 600
|
order: 600
|
||||||
- title: '📦 Other work'
|
- title: '📦 Other work'
|
||||||
|
regexp: '^chore(\([^)]*\))?:|^chore:'
|
||||||
order: 9999
|
order: 9999
|
||||||
sboms:
|
sboms:
|
||||||
- artifacts: archive
|
- artifacts: archive
|
||||||
|
|||||||
2
.ko.yaml
2
.ko.yaml
@@ -4,6 +4,6 @@ defaultPlatforms:
|
|||||||
- linux/arm
|
- linux/arm
|
||||||
builds:
|
builds:
|
||||||
- id: capsule
|
- id: capsule
|
||||||
main: ./
|
main: ./cmd/
|
||||||
ldflags:
|
ldflags:
|
||||||
- '{{ if index .Env "LD_FLAGS" }}{{ .Env.LD_FLAGS }}{{ end }}'
|
- '{{ if index .Env "LD_FLAGS" }}{{ .Env.LD_FLAGS }}{{ end }}'
|
||||||
|
|||||||
15
.nwa-config
Normal file
15
.nwa-config
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
nwa:
|
||||||
|
cmd: "update"
|
||||||
|
holder: "Project Capsule Authors"
|
||||||
|
year: "2020-2026"
|
||||||
|
spdxids: "Apache-2.0"
|
||||||
|
path:
|
||||||
|
- "pkg/**/*.go"
|
||||||
|
- "cmd/**/*.go"
|
||||||
|
- "api/**/*.go"
|
||||||
|
- "internal/**/*.go"
|
||||||
|
- "controllers/**/*.go"
|
||||||
|
- "main.go"
|
||||||
|
mute: false
|
||||||
|
verbose: true
|
||||||
|
fuzzy: true
|
||||||
@@ -1,20 +1,19 @@
|
|||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
|
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
|
||||||
rev: v9.20.0
|
rev: v9.24.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: commitlint
|
- id: commitlint
|
||||||
stages: [commit-msg]
|
stages: [commit-msg]
|
||||||
additional_dependencies: ['@commitlint/config-conventional', 'commitlint-plugin-function-rules']
|
additional_dependencies: ['@commitlint/config-conventional', 'commitlint-plugin-function-rules']
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v5.0.0
|
rev: v6.0.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-executables-have-shebangs
|
- id: check-executables-have-shebangs
|
||||||
- id: check-yaml
|
|
||||||
- id: double-quote-string-fixer
|
- id: double-quote-string-fixer
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- repo: https://github.com/adrienverge/yamllint
|
- repo: https://github.com/adrienverge/yamllint
|
||||||
rev: v1.35.1
|
rev: v1.38.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: yamllint
|
- id: yamllint
|
||||||
args: [-c=.github/configs/lintconf.yaml]
|
args: [-c=.github/configs/lintconf.yaml]
|
||||||
@@ -35,24 +34,13 @@ repos:
|
|||||||
entry: make helm-lint
|
entry: make helm-lint
|
||||||
language: system
|
language: system
|
||||||
files: ^charts/
|
files: ^charts/
|
||||||
# Currently too slow smw
|
- id: golangci-lint
|
||||||
# - id: golangci-lint
|
name: Execute golangci-lint
|
||||||
# name: Execute golangci-lint
|
entry: make golint
|
||||||
# entry: make golint
|
language: system
|
||||||
# language: system
|
files: \.go$
|
||||||
# files: \.go$
|
- id: go-test
|
||||||
# - repo: https://github.com/tekwizely/pre-commit-golang
|
name: Execute go test
|
||||||
# rev: v1.0.0-rc.1
|
entry: make test
|
||||||
# hooks:
|
language: system
|
||||||
# - id: go-vet
|
files: \.go$
|
||||||
# - id: go-vet-mod
|
|
||||||
# - id: go-vet-pkg
|
|
||||||
# - id: go-vet-repo-mod
|
|
||||||
# - id: go-vet-repo-pkg
|
|
||||||
# - id: go-revive
|
|
||||||
# - id: go-revive-mod
|
|
||||||
# - id: go-revive-repo-mod
|
|
||||||
# - id: go-sec-mod
|
|
||||||
# - id: go-sec-pkg
|
|
||||||
# - id: go-sec-repo-mod
|
|
||||||
# - id: go-sec-repo-pkg
|
|
||||||
|
|||||||
34
ADOPTERS.md
34
ADOPTERS.md
@@ -2,40 +2,48 @@
|
|||||||
|
|
||||||
This is a list of companies that have adopted Capsule, feel free to open a Pull-Request to get yours listed.
|
This is a list of companies that have adopted Capsule, feel free to open a Pull-Request to get yours listed.
|
||||||
|
|
||||||
|
[See all on the website](https://projectcapsule.dev/adopters/)
|
||||||
|
|
||||||
## Adopters list (alphabetically)
|
## Adopters list (alphabetically)
|
||||||
|
|
||||||
### [Bedag Informatik AG](https://www.bedag.ch/)
|
### [Bedag Informatik AG](https://www.bedag.ch/)
|
||||||

|
<img src="https://www.bedag.ch/wGlobal/wGlobal/layout/images/logo.svg" alt="Bedag" width="350" />
|
||||||
|
|
||||||
### [Department of Defense](https://www.defense.gov/)
|
### [Department of Defense](https://www.defense.gov/)
|
||||||

|
<img src="https://www.access-board.gov/images/dod-seal.png" alt="United States Department of Defense" width="350" />
|
||||||
|
|
||||||
### [KubeRocketCI](https://docs.kuberocketci.io/)
|
### [Enreach](https://www.enreach.com/)
|
||||||

|
<img src="https://campaigns.enreach.com/hubfs/Global/logos/Enreach-logo-vertical-indigo.svg" alt="Enreach" width="350" />
|
||||||
|
|
||||||
### [Fastweb](https://www.fastweb.it/)
|
### [Fastweb](https://www.fastweb.it/)
|
||||||

|
<img src="https://www.fastweb.it/var/storage_feeds/CMS-Company/articoli/0c2/0c252987b90a18017dedf2ed9feda129/640x360.jpg" alt="Fastweb" width="350" />
|
||||||
|
|
||||||
### [Klarrio](https://klarrio.com/)
|
### [Klarrio](https://klarrio.com/)
|
||||||

|
<img src="https://klarrio.com/wp-content/uploads/klarrio.png" alt="Klarrio" width="350" />
|
||||||
|
|
||||||
|
### [KubeRocketCI](https://docs.kuberocketci.io/)
|
||||||
|
<img src="https://raw.githubusercontent.com/epam/edp-install/master/docs/assets/krci-logo-267×150-white.png" alt="KubeRocketCI" width="350" />
|
||||||
|
|
||||||
|
### [ODC-Noord](https://odc-noord.nl/)
|
||||||
|
<img src="./assets/customer_logo/odc-noord-logo.png" alt="ODC-Noord" width="350" />
|
||||||
|
|
||||||
### [PITS Global Data Recovery Services](https://www.pitsdatarecovery.net)
|
### [PITS Global Data Recovery Services](https://www.pitsdatarecovery.net)
|
||||||

|
<img src="https://www.pitsdatarecovery.net/wp-content/uploads/2020/09/pits-logo.svg" alt="PITS Global Data Recovery Services" width="350" />
|
||||||
|
|
||||||
### [Politecnico di Torino](https://www.polito.it/)
|
### [Politecnico di Torino](https://www.polito.it/)
|
||||||

|
<img src="https://www.polito.it/themes/custom/polito/polito_logo_desktop.svg" alt="Politecnico di Torino" width="350" />
|
||||||
|
|
||||||
### [Reevo](https://www.reevo.it/)
|
### [Reevo](https://www.reevo.it/)
|
||||||

|
<img src="https://www.reevo.it/hs-fs/hubfs/logo_reevo_azzurro.png" alt="Reevo Cloud and CyberSecurity" width="350" />
|
||||||
|
|
||||||
### [Seeweb](https://seeweb.it/en)
|
### [Seeweb](https://seeweb.it/en)
|
||||||

|
<img src="https://www.seeweb.it/assets/images/logo-seeweb.svg" alt="Seeweb x Serverless GPU" width="350" />
|
||||||
|
|
||||||
### [University of Torino](https://www.unito.it)
|
### [University of Torino](https://www.unito.it)
|
||||||

|
<img src="https://www.unito.it/sites/all/themes/bsunito/img/logo_new_2022.svg" alt="University of Torino" width="350" />
|
||||||
|
|
||||||
### [Velocity](https://velocity.tech/)
|
### [Velocity](https://velocity.tech/)
|
||||||

|
<img src="https://raw.githubusercontent.com/yarelm/velocity-logo/main/velocity.png" alt="Velocity" width="350" />
|
||||||
|
|
||||||
### [Wargaming.net](https://www.wargaming.net/)
|
### [Wargaming.net](https://www.wargaming.net/)
|
||||||

|
<img src="https://download.logo.wine/logo/Wargaming_%28company%29/Wargaming_%28company%29-Logo.wine.png" alt="Wargaming.net" width="350" />
|
||||||
|
|||||||
@@ -186,4 +186,3 @@ The following types are allowed for commits and pull requests:
|
|||||||
* `fix`: bug fixes
|
* `fix`: bug fixes
|
||||||
* `test`: test related changes
|
* `test`: test related changes
|
||||||
* `sec`: security related changes
|
* `sec`: security related changes
|
||||||
|
|
||||||
|
|||||||
@@ -63,16 +63,19 @@ So the TL;DR answer is:
|
|||||||
**Make sure a *KinD* cluster is running on your laptop, and then run `make dev-setup` to setup the dev environment.**. This is not done in the `make dev-setup` setup.
|
**Make sure a *KinD* cluster is running on your laptop, and then run `make dev-setup` to setup the dev environment.**. This is not done in the `make dev-setup` setup.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# If you haven't installed or run `make deploy` before, do it first
|
# Create a KinD cluster if not already created
|
||||||
# Note: please retry if you saw errors
|
$ make dev-cluster
|
||||||
$ make deploy
|
|
||||||
|
|
||||||
# To retrieve your laptop's IP and execute `make dev-setup` to setup dev env
|
# To retrieve your laptop's IP and execute `make dev-setup` to setup dev env
|
||||||
# For example: LAPTOP_HOST_IP=192.168.10.101 make dev-setup
|
# For example: LAPTOP_HOST_IP=192.168.10.101 make dev-setup
|
||||||
$ LAPTOP_HOST_IP="<YOUR_LAPTOP_IP>" make dev-setup
|
$ LAPTOP_HOST_IP="<YOUR_LAPTOP_IP>" make dev-setup
|
||||||
|
|
||||||
|
|
||||||
|
# Monitoring Setup (Grafana/Prometheus/Pyroscope)
|
||||||
|
$ LAPTOP_HOST_IP="<YOUR_LAPTOP_IP>" make dev-setup-monitoring
|
||||||
```
|
```
|
||||||
|
|
||||||
### Explenation
|
### Setup
|
||||||
|
|
||||||
We recommend to setup the development environment with the make `dev-setup` target. However here is a step by step guide to setup the development environment for understanding.
|
We recommend to setup the development environment with the make `dev-setup` target. However here is a step by step guide to setup the development environment for understanding.
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ FROM ${TARGET_IMAGE} AS target
|
|||||||
# Inject Harpoon Image
|
# Inject Harpoon Image
|
||||||
FROM ghcr.io/alegrey91/harpoon:latest
|
FROM ghcr.io/alegrey91/harpoon:latest
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
COPY --from=target /ko-app/capsule ./manager
|
COPY --from=target /ko-app/cmd ./manager
|
||||||
|
RUN chmod +x ./harpoon
|
||||||
ENTRYPOINT ["/harpoon", \
|
ENTRYPOINT ["/harpoon", \
|
||||||
"capture", \
|
"capture", \
|
||||||
"-f", "main.main", \
|
"-f", "main.main", \
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ The current Maintainers Group for the [TODO: Projectname] Project consists of:
|
|||||||
| Dario Tranchitella | Clastix | Maintainer |
|
| Dario Tranchitella | Clastix | Maintainer |
|
||||||
| Maksim Fedotov | Wargaming | Maintainer |
|
| Maksim Fedotov | Wargaming | Maintainer |
|
||||||
| Oliver Bähler | Peak Scale | Maintainer |
|
| Oliver Bähler | Peak Scale | Maintainer |
|
||||||
|
| Hristo Hristov | Vaerolabs | Maintainer |
|
||||||
| Massimiliano Giovagnoli | Proximus | Maintainer |
|
| Massimiliano Giovagnoli | Proximus | Maintainer |
|
||||||
|
|
||||||
This list must be kept in sync with the [CNCF Project Maintainers list](https://github.com/cncf/foundation/blob/master/project-maintainers.csv).
|
This list must be kept in sync with the [CNCF Project Maintainers list](https://github.com/cncf/foundation/blob/master/project-maintainers.csv).
|
||||||
|
|||||||
189
Makefile
189
Makefile
@@ -19,7 +19,7 @@ CAPSULE_IMG ?= $(REGISTRY)/$(IMG_BASE)
|
|||||||
CLUSTER_NAME ?= capsule
|
CLUSTER_NAME ?= capsule
|
||||||
|
|
||||||
## Kubernetes Version Support
|
## Kubernetes Version Support
|
||||||
KUBERNETES_SUPPORTED_VERSION ?= "v1.31.0"
|
KUBERNETES_SUPPORTED_VERSION ?= "v1.35.0"
|
||||||
|
|
||||||
## Tool Binaries
|
## Tool Binaries
|
||||||
KUBECTL ?= kubectl
|
KUBECTL ?= kubectl
|
||||||
@@ -46,7 +46,7 @@ all: manager
|
|||||||
# Run tests
|
# Run tests
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: test-clean generate manifests test-clean
|
test: test-clean generate manifests test-clean
|
||||||
@GO111MODULE=on go test -v ./... -coverprofile coverage.out
|
@GO111MODULE=on go test -race -v $(shell go list ./... | grep -v "e2e") -coverprofile coverage.out
|
||||||
|
|
||||||
.PHONY: test-clean
|
.PHONY: test-clean
|
||||||
test-clean: ## Clean tests cache
|
test-clean: ## Clean tests cache
|
||||||
@@ -68,6 +68,11 @@ manifests: generate
|
|||||||
generate: controller-gen
|
generate: controller-gen
|
||||||
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
|
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
|
||||||
|
|
||||||
|
|
||||||
|
# Generate License Header
|
||||||
|
license-headers: nwa
|
||||||
|
$(NWA) config
|
||||||
|
|
||||||
# Helm
|
# Helm
|
||||||
SRC_ROOT = $(shell git rev-parse --show-toplevel)
|
SRC_ROOT = $(shell git rev-parse --show-toplevel)
|
||||||
|
|
||||||
@@ -82,25 +87,52 @@ helm-lint: ct
|
|||||||
@$(CT) lint --config .github/configs/ct.yaml --validate-yaml=false --all --debug
|
@$(CT) lint --config .github/configs/ct.yaml --validate-yaml=false --all --debug
|
||||||
|
|
||||||
helm-schema: helm-plugin-schema
|
helm-schema: helm-plugin-schema
|
||||||
cd charts/capsule && $(HELM) schema -output values.schema.json
|
cd charts/capsule && $(HELM) schema --use-helm-docs
|
||||||
|
|
||||||
helm-test: HELM_KIND_CONFIG ?= ""
|
helm-test: HELM_KIND_CONFIG ?= ""
|
||||||
helm-test: kind
|
helm-test: kind
|
||||||
@mkdir -p /tmp/results || true
|
@mkdir -p /tmp/results || true
|
||||||
@$(KIND) create cluster --wait=60s --name capsule-charts --image kindest/node:$(KUBERNETES_SUPPORTED_VERSION) --config $(HELM_KIND_CONFIG)
|
@$(KIND) create cluster --wait=60s --name capsule-charts --image kindest/node:$(KUBERNETES_SUPPORTED_VERSION) --config ./hack/kind-cluster.yaml
|
||||||
@make helm-test-exec
|
@make helm-test-exec
|
||||||
@$(KIND) delete cluster --name capsule-charts
|
@$(KIND) delete cluster --name capsule-charts
|
||||||
|
|
||||||
helm-test-exec: ct helm-controller-version ko-build-all
|
helm-test-exec: ct helm-controller-version ko-build-all
|
||||||
$(MAKE) docker-build-capsule-trace
|
|
||||||
$(MAKE) e2e-load-image CLUSTER_NAME=capsule-charts IMAGE=$(CAPSULE_IMG) VERSION=v0.0.0
|
$(MAKE) e2e-load-image CLUSTER_NAME=capsule-charts IMAGE=$(CAPSULE_IMG) VERSION=v0.0.0
|
||||||
$(MAKE) e2e-load-image CLUSTER_NAME=capsule-charts IMAGE=$(CAPSULE_IMG) VERSION=tracing
|
|
||||||
@$(KUBECTL) create ns capsule-system || true
|
@$(KUBECTL) create ns capsule-system || true
|
||||||
@$(KUBECTL) apply --force-conflicts --server-side=true -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.crds.yaml
|
$(MAKE) dev-install-deps
|
||||||
@$(KUBECTL) apply --force-conflicts --server-side=true -f https://github.com/prometheus-operator/prometheus-operator/releases/download/v0.58.0/bundle.yaml
|
$(MAKE) dev-install-grafana-operator-crds
|
||||||
@$(CT) install --config $(SRC_ROOT)/.github/configs/ct.yaml --namespace=capsule-system --all --debug
|
@$(CT) install --config $(SRC_ROOT)/.github/configs/ct.yaml --namespace=capsule-system --all --debug
|
||||||
|
|
||||||
# Setup development env
|
# Setup development env
|
||||||
|
dev-build: kind
|
||||||
|
$(KIND) create cluster --wait=60s --name $(CLUSTER_NAME) --image kindest/node:$(KUBERNETES_SUPPORTED_VERSION) --config ./hack/kind-cluster.yaml
|
||||||
|
$(MAKE) dev-install-deps
|
||||||
|
|
||||||
|
.PHONY: dev-destroy
|
||||||
|
dev-destroy: kind
|
||||||
|
$(KIND) delete cluster --name capsule
|
||||||
|
|
||||||
|
dev-install-deps: dev-setup-fluxcd dev-setup-cert-manager dev-install-gw-api-crds wait-for-helmreleases
|
||||||
|
|
||||||
|
API_GW := none
|
||||||
|
API_GW_VERSION := v1.3.0
|
||||||
|
API_GW_LOOKUP := kubernetes-sigs/gateway-api
|
||||||
|
dev-install-gw-api-crds:
|
||||||
|
@$(KUBECTL) apply --force-conflicts --server-side=true -f https://github.com/$(API_GW_LOOKUP)/releases/download/$(API_GW_VERSION)/standard-install.yaml
|
||||||
|
|
||||||
|
GRAFANA := none
|
||||||
|
GRAFANA_VERSION := v5.18.0
|
||||||
|
GRAFANA_LOOKUP := grafana/grafana-operator
|
||||||
|
dev-install-grafana-operator-crds:
|
||||||
|
@$(KUBECTL) apply --force-conflicts --server-side=true -f https://github.com/grafana/grafana-operator/releases/download/$(GRAFANA_VERSION)/crds.yaml
|
||||||
|
|
||||||
|
PROMETHEUS := none
|
||||||
|
PROMETHEUS_VERSION := v0.88.0
|
||||||
|
PROMETHEUS_LOOKUP := prometheus-operator/prometheus-operator
|
||||||
|
dev-install-prometheus-crds:
|
||||||
|
@$(KUBECTL) apply --force-conflicts --server-side=true -f https://github.com/prometheus-operator/prometheus-operator/releases/download/$(PROMETHEUS_VERSION)/bundle.yaml
|
||||||
|
|
||||||
|
|
||||||
# Usage:
|
# Usage:
|
||||||
# LAPTOP_HOST_IP=<YOUR_LAPTOP_IP> make dev-setup
|
# LAPTOP_HOST_IP=<YOUR_LAPTOP_IP> make dev-setup
|
||||||
# For example:
|
# For example:
|
||||||
@@ -123,6 +155,7 @@ IP.1 = $(LAPTOP_HOST_IP)
|
|||||||
endef
|
endef
|
||||||
export TLS_CNF
|
export TLS_CNF
|
||||||
dev-setup:
|
dev-setup:
|
||||||
|
$(KUBECTL) -n capsule-system scale deployment capsule-controller-manager --replicas=0 || true
|
||||||
mkdir -p /tmp/k8s-webhook-server/serving-certs
|
mkdir -p /tmp/k8s-webhook-server/serving-certs
|
||||||
echo "$${TLS_CNF}" > _tls.cnf
|
echo "$${TLS_CNF}" > _tls.cnf
|
||||||
openssl req -newkey rsa:4096 -days 3650 -nodes -x509 \
|
openssl req -newkey rsa:4096 -days 3650 -nodes -x509 \
|
||||||
@@ -139,18 +172,107 @@ dev-setup:
|
|||||||
export CA_BUNDLE=`openssl base64 -in /tmp/k8s-webhook-server/serving-certs/tls.crt | tr -d '\n'`; \
|
export CA_BUNDLE=`openssl base64 -in /tmp/k8s-webhook-server/serving-certs/tls.crt | tr -d '\n'`; \
|
||||||
$(HELM) upgrade \
|
$(HELM) upgrade \
|
||||||
--dependency-update \
|
--dependency-update \
|
||||||
|
--force-conflicts \
|
||||||
--debug \
|
--debug \
|
||||||
--install \
|
--install \
|
||||||
--namespace capsule-system \
|
--namespace capsule-system \
|
||||||
--create-namespace \
|
--create-namespace \
|
||||||
--set 'crds.install=true' \
|
--set 'crds.install=true' \
|
||||||
--set 'crds.exclusive=true'\
|
--set 'crds.exclusive=true'\
|
||||||
|
--set 'crds.createConfig=true'\
|
||||||
|
--set "tls.enableController=false"\
|
||||||
--set "webhooks.exclusive=true"\
|
--set "webhooks.exclusive=true"\
|
||||||
|
--set "webhooks.hooks.nodes.enabled=true"\
|
||||||
--set "webhooks.service.url=$${WEBHOOK_URL}" \
|
--set "webhooks.service.url=$${WEBHOOK_URL}" \
|
||||||
--set "webhooks.service.caBundle=$${CA_BUNDLE}" \
|
--set "webhooks.service.caBundle=$${CA_BUNDLE}" \
|
||||||
capsule \
|
capsule \
|
||||||
./charts/capsule
|
./charts/capsule || true
|
||||||
$(KUBECTL) -n capsule-system scale deployment capsule-controller-manager --replicas=0 || true
|
|
||||||
|
setup-monitoring: dev-setup-fluxcd
|
||||||
|
@$(KUBECTL) kustomize --load-restrictor='LoadRestrictionsNone' hack/distro/monitoring | envsubst | kubectl apply -f -
|
||||||
|
@$(KUBECTL) kustomize --load-restrictor='LoadRestrictionsNone' hack/distro/monitoring/dashboards | kubectl apply -f -
|
||||||
|
@$(MAKE) wait-for-helmreleases
|
||||||
|
@printf "\n\033[32mAccess Grafana:\033[0m\n\n"
|
||||||
|
@printf " \033[1mkubectl port-forward svc/kube-prometheus-stack-grafana 9090:80 -n monitoring-system\033[0m\n\n"
|
||||||
|
|
||||||
|
dev-setup-monitoring: setup-monitoring
|
||||||
|
@$(KUBECTL) kustomize --load-restrictor='LoadRestrictionsNone' hack/distro/host-proxy | envsubst | kubectl apply -f -
|
||||||
|
|
||||||
|
dev-setup-argocd: dev-setup-fluxcd
|
||||||
|
@$(KUBECTL) kustomize --load-restrictor='LoadRestrictionsNone' hack/distro/argocd | envsubst | kubectl apply -f -
|
||||||
|
@$(MAKE) wait-for-helmreleases
|
||||||
|
@$(KUBECTL) kustomize --load-restrictor='LoadRestrictionsNone' hack/distro/argocd/application | envsubst | kubectl apply -f -
|
||||||
|
@printf "\n\033[32mAccess ArgoCD:\033[0m\n\n"
|
||||||
|
@printf " \033[1mkubectl get secret -n argocd argocd-initial-admin-secret -o jsonpath='{.data.password}' | base64 -d\033[0m\n\n"
|
||||||
|
@printf " \033[1mkubectl port-forward svc/argocd-server 9091:80 -n argocd\033[0m\n\n"
|
||||||
|
|
||||||
|
dev-setup-cert-manager:
|
||||||
|
@$(KUBECTL) kustomize --load-restrictor='LoadRestrictionsNone' hack/distro/cert-manager | envsubst | kubectl apply -f -
|
||||||
|
|
||||||
|
dev-setup-fluxcd:
|
||||||
|
@$(KUBECTL) kustomize --load-restrictor='LoadRestrictionsNone' hack/distro/fluxcd | envsubst | kubectl apply -f -
|
||||||
|
|
||||||
|
|
||||||
|
# Here to setup the current capsule version
|
||||||
|
# Intended to test updates to new version
|
||||||
|
dev-setup-capsule: dev-setup-fluxcd
|
||||||
|
@$(KUBECTL) kustomize --load-restrictor='LoadRestrictionsNone' hack/distro/capsule | envsubst | kubectl apply -f -
|
||||||
|
@$(MAKE) wait-for-helmreleases
|
||||||
|
@$(MAKE) dev-setup-capsule-example
|
||||||
|
|
||||||
|
dev-setup-capsule-example: dev-setup-fluxcd
|
||||||
|
@$(KUBECTL) kustomize --load-restrictor='LoadRestrictionsNone' hack/distro/capsule/example-setup | envsubst | kubectl apply -f -
|
||||||
|
@$(KUBECTL) create ns wind-test --as joe --as-group projectcapsule.dev || true
|
||||||
|
@$(KUBECTL) create ns wind-prod --as joe --as-group projectcapsule.dev || true
|
||||||
|
@$(KUBECTL) create ns green-test --as bob --as-group projectcapsule.dev || true
|
||||||
|
@$(KUBECTL) create ns green-prod --as bob --as-group projectcapsule.dev || true
|
||||||
|
@$(KUBECTL) create ns solar-test --as alice --as-group projectcapsule.dev || true
|
||||||
|
@$(KUBECTL) create ns solar-prod --as alice --as-group projectcapsule.dev || true
|
||||||
|
@$(KUBECTL) apply -f hack/distro/capsule/example-setup/claims.yaml
|
||||||
|
|
||||||
|
|
||||||
|
wait-for-helmreleases:
|
||||||
|
@ echo "Waiting for all HelmReleases to have observedGeneration >= 0..."
|
||||||
|
@while [ "$$($(KUBECTL) get helmrelease -A -o jsonpath='{range .items[?(@.status.observedGeneration<0)]}{.metadata.namespace}{" "}{.metadata.name}{"\n"}{end}' | wc -l)" -ne 0 ]; do \
|
||||||
|
sleep 5; \
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
ENTERPRISE_VERSION ?= "0.13.0-rc.2"
|
||||||
|
ENTERPRISE_REGISTRY ?= "oci.peakscale.ch"
|
||||||
|
|
||||||
|
enterprise-prerelease:
|
||||||
|
mkdir -p ./builds
|
||||||
|
$(MAKE) CAPSULE_IMG=$(ENTERPRISE_REGISTRY)/prereleases/images/capsule VERSION=$(ENTERPRISE_VERSION) ko-publish-capsule
|
||||||
|
$(HELM) package ./charts/capsule --app-version=$(ENTERPRISE_VERSION) --version=$(ENTERPRISE_VERSION) --destination ./builds/
|
||||||
|
$(HELM) push ./builds/capsule-$(ENTERPRISE_VERSION).tgz oci://$(ENTERPRISE_REGISTRY)/prereleases/charts/
|
||||||
|
$(MAKE) deploy-enterprise
|
||||||
|
rm -rf ./builds
|
||||||
|
|
||||||
|
deploy-enterprise:
|
||||||
|
@echo ""
|
||||||
|
@echo "Deploying Capsule Prerelease (Enterprise) $(ENTERPRISE_VERSION)"
|
||||||
|
@echo ""
|
||||||
|
@echo "1) Create image pull secret (Change the credentials with the ones provided to you):"
|
||||||
|
@echo ""
|
||||||
|
@echo "kubectl create secret docker-registry capsule-enterprise -n capsule-system \\"
|
||||||
|
@echo " --docker-username='robot\$$name' \\"
|
||||||
|
@echo " --docker-password='serviceaccount-password' \\"
|
||||||
|
@echo " --docker-server='$(ENTERPRISE_REGISTRY)'"
|
||||||
|
@echo ""
|
||||||
|
@echo "2) Deploy Capsule:"
|
||||||
|
@echo ""
|
||||||
|
@echo "helm upgrade --install capsule \\"
|
||||||
|
@echo " oci://$(ENTERPRISE_REGISTRY)/prereleases/charts/capsule \\"
|
||||||
|
@echo " --namespace capsule-system \\"
|
||||||
|
@echo " --version $(ENTERPRISE_VERSION) \\"
|
||||||
|
@echo " --reuse-values \\"
|
||||||
|
@echo " --set manager.image.registry=$(ENTERPRISE_REGISTRY) \\"
|
||||||
|
@echo " --set manager.image.repository=prereleases/images/capsule \\"
|
||||||
|
@echo " --set manager.image.tag=$(ENTERPRISE_VERSION) \\"
|
||||||
|
@echo " --set manager.image.pullPolicy=Always \\"
|
||||||
|
@echo " --set 'serviceAccount.imagePullSecrets={capsule-enterprise}'"
|
||||||
|
@echo ""
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# -- Docker
|
# -- Docker
|
||||||
@@ -178,7 +300,7 @@ LD_FLAGS := "-X main.Version=$(VERSION) \
|
|||||||
ko-build-capsule: ko
|
ko-build-capsule: ko
|
||||||
@echo Building Capsule $(KO_TAGS) for $(KO_PLATFORM) >&2
|
@echo Building Capsule $(KO_TAGS) for $(KO_PLATFORM) >&2
|
||||||
@LD_FLAGS=$(LD_FLAGS) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(CAPSULE_IMG) \
|
@LD_FLAGS=$(LD_FLAGS) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(CAPSULE_IMG) \
|
||||||
$(KO) build ./ --bare --tags=$(KO_TAGS) --push=false --local --platform=$(KO_PLATFORM)
|
$(KO) build ./cmd/ --bare --tags=$(KO_TAGS) --push=false --local --platform=$(KO_PLATFORM)
|
||||||
|
|
||||||
.PHONY: ko-build-all
|
.PHONY: ko-build-all
|
||||||
ko-build-all: ko-build-capsule
|
ko-build-all: ko-build-capsule
|
||||||
@@ -204,7 +326,7 @@ ko-login: ko
|
|||||||
.PHONY: ko-publish-capsule
|
.PHONY: ko-publish-capsule
|
||||||
ko-publish-capsule: ko-login ## Build and publish kyvernopre image (with ko)
|
ko-publish-capsule: ko-login ## Build and publish kyvernopre image (with ko)
|
||||||
@LD_FLAGS=$(LD_FLAGS) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(CAPSULE_IMG) \
|
@LD_FLAGS=$(LD_FLAGS) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(CAPSULE_IMG) \
|
||||||
$(KO) build ./ --bare --tags=$(KO_TAGS)
|
$(KO) build ./cmd/ --bare --tags=$(KO_TAGS)
|
||||||
|
|
||||||
.PHONY: ko-publish-all
|
.PHONY: ko-publish-all
|
||||||
ko-publish-all: ko-publish-capsule
|
ko-publish-all: ko-publish-capsule
|
||||||
@@ -217,7 +339,12 @@ goimports:
|
|||||||
# Linting code as PR is expecting
|
# Linting code as PR is expecting
|
||||||
.PHONY: golint
|
.PHONY: golint
|
||||||
golint: golangci-lint
|
golint: golangci-lint
|
||||||
$(GOLANGCI_LINT) run -c .golangci.yml --verbose --fix
|
$(GOLANGCI_LINT) run -c .golangci.yaml --verbose
|
||||||
|
|
||||||
|
.PHONY: golint-fix
|
||||||
|
golint-fix: golangci-lint
|
||||||
|
$(GOLANGCI_LINT) run -c .golangci.yaml --verbose --fix
|
||||||
|
|
||||||
|
|
||||||
# Running e2e tests in a KinD instance
|
# Running e2e tests in a KinD instance
|
||||||
.PHONY: e2e
|
.PHONY: e2e
|
||||||
@@ -225,11 +352,11 @@ e2e: ginkgo
|
|||||||
$(MAKE) e2e-build && $(MAKE) e2e-exec && $(MAKE) e2e-destroy
|
$(MAKE) e2e-build && $(MAKE) e2e-exec && $(MAKE) e2e-destroy
|
||||||
|
|
||||||
e2e-build: kind
|
e2e-build: kind
|
||||||
$(KIND) create cluster --wait=60s --name $(CLUSTER_NAME) --image kindest/node:$(KUBERNETES_SUPPORTED_VERSION)
|
$(MAKE) dev-build
|
||||||
$(MAKE) e2e-install
|
$(MAKE) e2e-install
|
||||||
|
|
||||||
.PHONY: e2e-install
|
.PHONY: e2e-install
|
||||||
e2e-install: ko-build-all
|
e2e-install: helm-controller-version ko-build-all
|
||||||
$(MAKE) e2e-load-image CLUSTER_NAME=$(CLUSTER_NAME) IMAGE=$(CAPSULE_IMG) VERSION=$(VERSION)
|
$(MAKE) e2e-load-image CLUSTER_NAME=$(CLUSTER_NAME) IMAGE=$(CAPSULE_IMG) VERSION=$(VERSION)
|
||||||
$(HELM) upgrade \
|
$(HELM) upgrade \
|
||||||
--dependency-update \
|
--dependency-update \
|
||||||
@@ -237,11 +364,14 @@ e2e-install: ko-build-all
|
|||||||
--install \
|
--install \
|
||||||
--namespace capsule-system \
|
--namespace capsule-system \
|
||||||
--create-namespace \
|
--create-namespace \
|
||||||
|
--set 'replicaCount=2'\
|
||||||
--set 'manager.image.pullPolicy=Never' \
|
--set 'manager.image.pullPolicy=Never' \
|
||||||
--set 'manager.resources=null'\
|
--set 'manager.resources=null'\
|
||||||
--set "manager.image.tag=$(VERSION)" \
|
--set "manager.image.tag=$(VERSION)" \
|
||||||
--set 'manager.livenessProbe.failureThreshold=10' \
|
--set 'manager.livenessProbe.failureThreshold=10' \
|
||||||
--set 'manager.readinessProbe.failureThreshold=10' \
|
--set 'webhooks.hooks.nodes.enabled=true' \
|
||||||
|
--set "webhooks.exclusive=true"\
|
||||||
|
--set "manager.options.logLevel=debug"\
|
||||||
capsule \
|
capsule \
|
||||||
./charts/capsule
|
./charts/capsule
|
||||||
|
|
||||||
@@ -266,6 +396,7 @@ trace-e2e: kind
|
|||||||
$(KIND) create cluster --wait=60s --image kindest/node:$(KUBERNETES_SUPPORTED_VERSION) --config hack/kind-cluster.yml
|
$(KIND) create cluster --wait=60s --image kindest/node:$(KUBERNETES_SUPPORTED_VERSION) --config hack/kind-cluster.yml
|
||||||
$(MAKE) e2e-load-image CLUSTER_NAME=capsule-tracing IMAGE=$(CAPSULE_IMG) VERSION=tracing
|
$(MAKE) e2e-load-image CLUSTER_NAME=capsule-tracing IMAGE=$(CAPSULE_IMG) VERSION=tracing
|
||||||
$(MAKE) trace-install
|
$(MAKE) trace-install
|
||||||
|
$(MAKE) e2e-install-deps
|
||||||
$(MAKE) e2e-exec
|
$(MAKE) e2e-exec
|
||||||
$(KIND) delete cluster --name capsule-tracing
|
$(KIND) delete cluster --name capsule-tracing
|
||||||
|
|
||||||
@@ -287,8 +418,7 @@ e2e-exec: ginkgo
|
|||||||
$(GINKGO) -v -tags e2e ./e2e
|
$(GINKGO) -v -tags e2e ./e2e
|
||||||
|
|
||||||
.PHONY: e2e-destroy
|
.PHONY: e2e-destroy
|
||||||
e2e-destroy: kind
|
e2e-destroy: dev-destroy
|
||||||
$(KIND) delete cluster --name capsule
|
|
||||||
|
|
||||||
SPELL_CHECKER = npx spellchecker-cli
|
SPELL_CHECKER = npx spellchecker-cli
|
||||||
docs-lint:
|
docs-lint:
|
||||||
@@ -312,7 +442,7 @@ $(LOCALBIN):
|
|||||||
|
|
||||||
HELM_SCHEMA_VERSION := ""
|
HELM_SCHEMA_VERSION := ""
|
||||||
helm-plugin-schema:
|
helm-plugin-schema:
|
||||||
@$(HELM) plugin install https://github.com/losisin/helm-values-schema-json.git --version $(HELM_SCHEMA_VERSION) || true
|
@$(HELM) plugin install https://github.com/losisin/helm-values-schema-json.git --version $(HELM_SCHEMA_VERSION) --verify=false || true
|
||||||
|
|
||||||
HELM_DOCS := $(LOCALBIN)/helm-docs
|
HELM_DOCS := $(LOCALBIN)/helm-docs
|
||||||
HELM_DOCS_VERSION := v1.14.1
|
HELM_DOCS_VERSION := v1.14.1
|
||||||
@@ -325,7 +455,7 @@ helm-doc:
|
|||||||
# -- Tools
|
# -- Tools
|
||||||
####################
|
####################
|
||||||
CONTROLLER_GEN := $(LOCALBIN)/controller-gen
|
CONTROLLER_GEN := $(LOCALBIN)/controller-gen
|
||||||
CONTROLLER_GEN_VERSION ?= v0.17.2
|
CONTROLLER_GEN_VERSION ?= v0.20.0
|
||||||
CONTROLLER_GEN_LOOKUP := kubernetes-sigs/controller-tools
|
CONTROLLER_GEN_LOOKUP := kubernetes-sigs/controller-tools
|
||||||
controller-gen:
|
controller-gen:
|
||||||
@test -s $(CONTROLLER_GEN) && $(CONTROLLER_GEN) --version | grep -q $(CONTROLLER_GEN_VERSION) || \
|
@test -s $(CONTROLLER_GEN) && $(CONTROLLER_GEN) --version | grep -q $(CONTROLLER_GEN_VERSION) || \
|
||||||
@@ -336,32 +466,39 @@ ginkgo:
|
|||||||
$(call go-install-tool,$(GINKGO),github.com/onsi/ginkgo/v2/ginkgo)
|
$(call go-install-tool,$(GINKGO),github.com/onsi/ginkgo/v2/ginkgo)
|
||||||
|
|
||||||
CT := $(LOCALBIN)/ct
|
CT := $(LOCALBIN)/ct
|
||||||
CT_VERSION := v3.12.0
|
CT_VERSION := v3.14.0
|
||||||
CT_LOOKUP := helm/chart-testing
|
CT_LOOKUP := helm/chart-testing
|
||||||
ct:
|
ct:
|
||||||
@test -s $(CT) && $(CT) version | grep -q $(CT_VERSION) || \
|
@test -s $(CT) && $(CT) version | grep -q $(CT_VERSION) || \
|
||||||
$(call go-install-tool,$(CT),github.com/$(CT_LOOKUP)/v3/ct@$(CT_VERSION))
|
$(call go-install-tool,$(CT),github.com/$(CT_LOOKUP)/v3/ct@$(CT_VERSION))
|
||||||
|
|
||||||
KIND := $(LOCALBIN)/kind
|
KIND := $(LOCALBIN)/kind
|
||||||
KIND_VERSION := v0.26.0
|
KIND_VERSION := v0.31.0
|
||||||
KIND_LOOKUP := kubernetes-sigs/kind
|
KIND_LOOKUP := kubernetes-sigs/kind
|
||||||
kind:
|
kind:
|
||||||
@test -s $(KIND) && $(KIND) --version | grep -q $(KIND_VERSION) || \
|
@test -s $(KIND) && $(KIND) --version | grep -q $(KIND_VERSION) || \
|
||||||
$(call go-install-tool,$(KIND),sigs.k8s.io/kind/cmd/kind@$(KIND_VERSION))
|
$(call go-install-tool,$(KIND),sigs.k8s.io/kind/cmd/kind@$(KIND_VERSION))
|
||||||
|
|
||||||
KO := $(LOCALBIN)/ko
|
KO := $(LOCALBIN)/ko
|
||||||
KO_VERSION := v0.17.1
|
KO_VERSION := v0.18.1
|
||||||
KO_LOOKUP := google/ko
|
KO_LOOKUP := google/ko
|
||||||
ko:
|
ko:
|
||||||
@test -s $(KO) && $(KO) -h | grep -q $(KO_VERSION) || \
|
@test -s $(KO) && $(KO) -h | grep -q $(KO_VERSION) || \
|
||||||
$(call go-install-tool,$(KO),github.com/$(KO_LOOKUP)@$(KO_VERSION))
|
$(call go-install-tool,$(KO),github.com/$(KO_LOOKUP)@$(KO_VERSION))
|
||||||
|
|
||||||
|
NWA := $(LOCALBIN)/nwa
|
||||||
|
NWA_VERSION := v0.7.7
|
||||||
|
NWA_LOOKUP := B1NARY-GR0UP/nwa
|
||||||
|
nwa:
|
||||||
|
@test -s $(NWA) && $(NWA) -h | grep -q $(NWA_VERSION) || \
|
||||||
|
$(call go-install-tool,$(NWA),github.com/$(NWA_LOOKUP)@$(NWA_VERSION))
|
||||||
|
|
||||||
GOLANGCI_LINT := $(LOCALBIN)/golangci-lint
|
GOLANGCI_LINT := $(LOCALBIN)/golangci-lint
|
||||||
GOLANGCI_LINT_VERSION := v1.63.4
|
GOLANGCI_LINT_VERSION := v2.8.0
|
||||||
GOLANGCI_LINT_LOOKUP := golangci/golangci-lint
|
GOLANGCI_LINT_LOOKUP := golangci/golangci-lint
|
||||||
golangci-lint: ## Download golangci-lint locally if necessary.
|
golangci-lint: ## Download golangci-lint locally if necessary.
|
||||||
@test -s $(GOLANGCI_LINT) && $(GOLANGCI_LINT) -h | grep -q $(GOLANGCI_LINT_VERSION) || \
|
@test -s $(GOLANGCI_LINT) && $(GOLANGCI_LINT) -h | grep -q $(GOLANGCI_LINT_VERSION) || \
|
||||||
$(call go-install-tool,$(GOLANGCI_LINT),github.com/$(GOLANGCI_LINT_LOOKUP)/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION))
|
$(call go-install-tool,$(GOLANGCI_LINT),github.com/$(GOLANGCI_LINT_LOOKUP)/v2/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION))
|
||||||
|
|
||||||
APIDOCS_GEN := $(LOCALBIN)/crdoc
|
APIDOCS_GEN := $(LOCALBIN)/crdoc
|
||||||
APIDOCS_GEN_VERSION := v0.6.4
|
APIDOCS_GEN_VERSION := v0.6.4
|
||||||
@@ -371,7 +508,7 @@ apidocs-gen: ## Download crdoc locally if necessary.
|
|||||||
$(call go-install-tool,$(APIDOCS_GEN),fybrik.io/crdoc@$(APIDOCS_GEN_VERSION))
|
$(call go-install-tool,$(APIDOCS_GEN),fybrik.io/crdoc@$(APIDOCS_GEN_VERSION))
|
||||||
|
|
||||||
HARPOON := $(LOCALBIN)/harpoon
|
HARPOON := $(LOCALBIN)/harpoon
|
||||||
HARPOON_VERSION := v0.9.6
|
HARPOON_VERSION := v0.10.2
|
||||||
HARPOON_LOOKUP := alegrey91/harpoon
|
HARPOON_LOOKUP := alegrey91/harpoon
|
||||||
harpoon:
|
harpoon:
|
||||||
@mkdir $(LOCALBIN)
|
@mkdir $(LOCALBIN)
|
||||||
|
|||||||
29
PROJECT
29
PROJECT
@@ -1,6 +1,10 @@
|
|||||||
|
# Code generated by tool. DO NOT EDIT.
|
||||||
|
# This file is used to track the info used to scaffold your project
|
||||||
|
# and allow the plugins properly work.
|
||||||
|
# More info: https://book.kubebuilder.io/reference/project-config.html
|
||||||
domain: clastix.io
|
domain: clastix.io
|
||||||
layout:
|
layout:
|
||||||
- go.kubebuilder.io/v3
|
- go.kubebuilder.io/v4
|
||||||
plugins:
|
plugins:
|
||||||
manifests.sdk.operatorframework.io/v2: {}
|
manifests.sdk.operatorframework.io/v2: {}
|
||||||
scorecard.sdk.operatorframework.io/v2: {}
|
scorecard.sdk.operatorframework.io/v2: {}
|
||||||
@@ -44,4 +48,27 @@ resources:
|
|||||||
kind: GlobalTenantResource
|
kind: GlobalTenantResource
|
||||||
path: github.com/projectcapsule/capsule/api/v1beta2
|
path: github.com/projectcapsule/capsule/api/v1beta2
|
||||||
version: v1beta2
|
version: v1beta2
|
||||||
|
- api:
|
||||||
|
crdVersion: v1
|
||||||
|
domain: clastix.io
|
||||||
|
group: capsule
|
||||||
|
kind: ResourcePool
|
||||||
|
path: github.com/projectcapsule/capsule/api/v1beta2
|
||||||
|
version: v1beta2
|
||||||
|
- api:
|
||||||
|
crdVersion: v1
|
||||||
|
namespaced: true
|
||||||
|
controller: true
|
||||||
|
domain: clastix.io
|
||||||
|
group: capsule
|
||||||
|
kind: ResourcePoolClaim
|
||||||
|
path: github.com/projectcapsule/capsule/api/v1beta2
|
||||||
|
version: v1beta2
|
||||||
|
- api:
|
||||||
|
crdVersion: v1
|
||||||
|
domain: clastix.io
|
||||||
|
group: capsule
|
||||||
|
kind: TenantOwner
|
||||||
|
path: github.com/projectcapsule/capsule/api/v1beta2
|
||||||
|
version: v1beta2
|
||||||
version: "3"
|
version: "3"
|
||||||
|
|||||||
16
README.md
16
README.md
@@ -23,7 +23,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="assets/logo/capsule_medium.png" />
|
<img src="assets/logo/capsule.svg" height=560 />
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -76,7 +76,7 @@ Assign to tenants a dedicated set of compute, storage, and network resources and
|
|||||||
|
|
||||||
# Documentation
|
# Documentation
|
||||||
|
|
||||||
Please, check the project [documentation](https://projectcapsule.dev) for the cool things you can do with Capsule.
|
Please check the project [documentation](https://projectcapsule.dev) for the cool things you can do with Capsule.
|
||||||
|
|
||||||
# Contributions
|
# Contributions
|
||||||
|
|
||||||
@@ -98,11 +98,11 @@ You can find how the Capsule project is governed [here](https://projectcapsule.d
|
|||||||
|
|
||||||
## Maintainers
|
## Maintainers
|
||||||
|
|
||||||
Please, refer to the maintainers file available [here](.github/maintainers.yaml).
|
Please refer to the maintainers file available [here](.github/maintainers.yaml).
|
||||||
|
|
||||||
## CLOMonitor
|
## CLOMonitor
|
||||||
|
|
||||||
CLOMonitor is a tool that periodically checks open source projects repositories to verify they meet certain project health best practices.
|
CLOMonitor is a tool that periodically checks open source project repositories to verify they meet certain project health best practices.
|
||||||
|
|
||||||
[](https://clomonitor.io/projects/cncf/capsule)
|
[](https://clomonitor.io/projects/cncf/capsule)
|
||||||
|
|
||||||
@@ -112,21 +112,21 @@ Read how we log changes [here](CHANGELOG.md)
|
|||||||
|
|
||||||
### Software Bill of Materials
|
### Software Bill of Materials
|
||||||
|
|
||||||
All OCI release artifacts include a Software Bill of Materials (SBOM) in CycloneDX JSON format. More information on this is available [here](SECURITY.md#software-bill-of-materials-sbom)
|
All OCI release artifacts include a Software Bill of Materials (SBOM) in CycloneDX JSON format. More information about this is available [here](SECURITY.md#software-bill-of-materials-sbom)
|
||||||
|
|
||||||
# FAQ
|
# FAQ
|
||||||
|
|
||||||
- Q. How to pronounce Capsule?
|
- Q. How do you pronounce Capsule?
|
||||||
|
|
||||||
A. It should be pronounced as `/ˈkæpsjuːl/`.
|
A. It should be pronounced as `/ˈkæpsjuːl/`.
|
||||||
|
|
||||||
- Q. Is it production grade?
|
- Q. Is it production grade?
|
||||||
|
|
||||||
A. Although under frequent development and improvements, Capsule is ready to be used in production environments as currently, people are using it in public and private deployments. Check out the [release](https://github.com/projectcapsule/capsule/releases) page for a detailed list of available versions.
|
A. Although under frequent development and improvement, Capsule is ready to be used in production environments as currently, people are using it in public and private deployments. Check out the [release](https://github.com/projectcapsule/capsule/releases) page for a detailed list of available versions.
|
||||||
|
|
||||||
- Q. Does it work with my Kubernetes XYZ distribution?
|
- Q. Does it work with my Kubernetes XYZ distribution?
|
||||||
|
|
||||||
A. We tested Capsule with vanilla Kubernetes 1.16+ on private environments and public clouds. We expect it to work smoothly on any other Kubernetes distribution. Please, let us know if you find it doesn't.
|
A. We tested Capsule with vanilla Kubernetes 1.16+ on private environments and public clouds. We expect it to work smoothly on any other Kubernetes distribution. Please let us know if you find it doesn't.
|
||||||
|
|
||||||
- Q. Do you provide commercial support?
|
- Q. Do you provide commercial support?
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta1
|
package v1beta1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta1
|
package v1beta1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Package v1beta1 contains API Schema definitions for the capsule v1beta1 API group
|
// Package v1beta1 contains API Schema definitions for the capsule v1beta1 API group
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta1
|
package v1beta1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta1
|
package v1beta1
|
||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/projectcapsule/capsule/pkg/api"
|
"github.com/projectcapsule/capsule/pkg/api"
|
||||||
|
"github.com/projectcapsule/capsule/pkg/api/meta"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NamespaceOptions struct {
|
type NamespaceOptions struct {
|
||||||
@@ -18,11 +19,11 @@ type NamespaceOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (in *Tenant) hasForbiddenNamespaceLabelsAnnotations() bool {
|
func (in *Tenant) hasForbiddenNamespaceLabelsAnnotations() bool {
|
||||||
if _, ok := in.Annotations[api.ForbiddenNamespaceLabelsAnnotation]; ok {
|
if _, ok := in.Annotations[meta.ForbiddenNamespaceLabelsAnnotation]; ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := in.Annotations[api.ForbiddenNamespaceLabelsRegexpAnnotation]; ok {
|
if _, ok := in.Annotations[meta.ForbiddenNamespaceLabelsRegexpAnnotation]; ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,11 +31,11 @@ func (in *Tenant) hasForbiddenNamespaceLabelsAnnotations() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (in *Tenant) hasForbiddenNamespaceAnnotationsAnnotations() bool {
|
func (in *Tenant) hasForbiddenNamespaceAnnotationsAnnotations() bool {
|
||||||
if _, ok := in.Annotations[api.ForbiddenNamespaceAnnotationsAnnotation]; ok {
|
if _, ok := in.Annotations[meta.ForbiddenNamespaceAnnotationsAnnotation]; ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := in.Annotations[api.ForbiddenNamespaceAnnotationsRegexpAnnotation]; ok {
|
if _, ok := in.Annotations[meta.ForbiddenNamespaceAnnotationsRegexpAnnotation]; ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,8 +48,8 @@ func (in *Tenant) ForbiddenUserNamespaceLabels() *api.ForbiddenListSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &api.ForbiddenListSpec{
|
return &api.ForbiddenListSpec{
|
||||||
Exact: strings.Split(in.Annotations[api.ForbiddenNamespaceLabelsAnnotation], ","),
|
Exact: strings.Split(in.Annotations[meta.ForbiddenNamespaceLabelsAnnotation], ","),
|
||||||
Regex: in.Annotations[api.ForbiddenNamespaceLabelsRegexpAnnotation],
|
Regex: in.Annotations[meta.ForbiddenNamespaceLabelsRegexpAnnotation],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ func (in *Tenant) ForbiddenUserNamespaceAnnotations() *api.ForbiddenListSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &api.ForbiddenListSpec{
|
return &api.ForbiddenListSpec{
|
||||||
Exact: strings.Split(in.Annotations[api.ForbiddenNamespaceAnnotationsAnnotation], ","),
|
Exact: strings.Split(in.Annotations[meta.ForbiddenNamespaceAnnotationsAnnotation], ","),
|
||||||
Regex: in.Annotations[api.ForbiddenNamespaceAnnotationsRegexpAnnotation],
|
Regex: in.Annotations[meta.ForbiddenNamespaceAnnotationsRegexpAnnotation],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta1
|
package v1beta1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta1
|
package v1beta1
|
||||||
@@ -19,7 +19,7 @@ func (in OwnerListSpec) FindOwner(name string, kind OwnerKind) (owner OwnerSpec)
|
|||||||
return in[i]
|
return in[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return owner
|
||||||
}
|
}
|
||||||
|
|
||||||
type ByKindAndName OwnerListSpec
|
type ByKindAndName OwnerListSpec
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta1
|
package v1beta1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta1
|
package v1beta1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta1
|
package v1beta1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta1
|
package v1beta1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta1
|
package v1beta1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta1
|
package v1beta1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta1
|
package v1beta1
|
||||||
@@ -20,17 +20,21 @@ type TenantSpec struct {
|
|||||||
// Specifies the allowed StorageClasses assigned to the Tenant. Capsule assures that all PersistentVolumeClaim resources created in the Tenant can use only one of the allowed StorageClasses. Optional.
|
// Specifies the allowed StorageClasses assigned to the Tenant. Capsule assures that all PersistentVolumeClaim resources created in the Tenant can use only one of the allowed StorageClasses. Optional.
|
||||||
StorageClasses *api.AllowedListSpec `json:"storageClasses,omitempty"`
|
StorageClasses *api.AllowedListSpec `json:"storageClasses,omitempty"`
|
||||||
// Specifies options for the Ingress resources, such as allowed hostnames and IngressClass. Optional.
|
// Specifies options for the Ingress resources, such as allowed hostnames and IngressClass. Optional.
|
||||||
IngressOptions IngressOptions `json:"ingressOptions,omitempty"`
|
// +optional
|
||||||
|
IngressOptions IngressOptions `json:"ingressOptions,omitzero"`
|
||||||
// Specifies the trusted Image Registries assigned to the Tenant. Capsule assures that all Pods resources created in the Tenant can use only one of the allowed trusted registries. Optional.
|
// Specifies the trusted Image Registries assigned to the Tenant. Capsule assures that all Pods resources created in the Tenant can use only one of the allowed trusted registries. Optional.
|
||||||
ContainerRegistries *api.AllowedListSpec `json:"containerRegistries,omitempty"`
|
ContainerRegistries *api.AllowedListSpec `json:"containerRegistries,omitempty"`
|
||||||
// Specifies the label to control the placement of pods on a given pool of worker nodes. All namespaces created within the Tenant will have the node selector annotation. This annotation tells the Kubernetes scheduler to place pods on the nodes having the selector label. Optional.
|
// Specifies the label to control the placement of pods on a given pool of worker nodes. All namespaces created within the Tenant will have the node selector annotation. This annotation tells the Kubernetes scheduler to place pods on the nodes having the selector label. Optional.
|
||||||
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
|
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
|
||||||
// Specifies the NetworkPolicies assigned to the Tenant. The assigned NetworkPolicies are inherited by any namespace created in the Tenant. Optional.
|
// Specifies the NetworkPolicies assigned to the Tenant. The assigned NetworkPolicies are inherited by any namespace created in the Tenant. Optional.
|
||||||
NetworkPolicies api.NetworkPolicySpec `json:"networkPolicies,omitempty"`
|
// +optional
|
||||||
|
NetworkPolicies api.NetworkPolicySpec `json:"networkPolicies,omitzero"`
|
||||||
// Specifies the resource min/max usage restrictions to the Tenant. The assigned values are inherited by any namespace created in the Tenant. Optional.
|
// Specifies the resource min/max usage restrictions to the Tenant. The assigned values are inherited by any namespace created in the Tenant. Optional.
|
||||||
LimitRanges api.LimitRangesSpec `json:"limitRanges,omitempty"`
|
// +optional
|
||||||
|
LimitRanges api.LimitRangesSpec `json:"limitRanges,omitzero"`
|
||||||
// Specifies a list of ResourceQuota resources assigned to the Tenant. The assigned values are inherited by any namespace created in the Tenant. The Capsule operator aggregates ResourceQuota at Tenant level, so that the hard quota is never crossed for the given Tenant. This permits the Tenant owner to consume resources in the Tenant regardless of the namespace. Optional.
|
// Specifies a list of ResourceQuota resources assigned to the Tenant. The assigned values are inherited by any namespace created in the Tenant. The Capsule operator aggregates ResourceQuota at Tenant level, so that the hard quota is never crossed for the given Tenant. This permits the Tenant owner to consume resources in the Tenant regardless of the namespace. Optional.
|
||||||
ResourceQuota api.ResourceQuotaSpec `json:"resourceQuotas,omitempty"`
|
// +optional
|
||||||
|
ResourceQuota api.ResourceQuotaSpec `json:"resourceQuotas,omitzero"`
|
||||||
// Specifies additional RoleBindings assigned to the Tenant. Capsule will ensure that all namespaces in the Tenant always contain the RoleBinding for the given ClusterRole. Optional.
|
// Specifies additional RoleBindings assigned to the Tenant. Capsule will ensure that all namespaces in the Tenant always contain the RoleBinding for the given ClusterRole. Optional.
|
||||||
AdditionalRoleBindings []api.AdditionalRoleBindingsSpec `json:"additionalRoleBindings,omitempty"`
|
AdditionalRoleBindings []api.AdditionalRoleBindingsSpec `json:"additionalRoleBindings,omitempty"`
|
||||||
// Specify the allowed values for the imagePullPolicies option in Pod resources. Capsule assures that all Pod resources created in the Tenant can use only one of the allowed policy. Optional.
|
// Specify the allowed values for the imagePullPolicies option in Pod resources. Capsule assures that all Pod resources created in the Tenant can use only one of the allowed policy. Optional.
|
||||||
@@ -51,10 +55,12 @@ type TenantSpec struct {
|
|||||||
// Tenant is the Schema for the tenants API.
|
// Tenant is the Schema for the tenants API.
|
||||||
type Tenant struct {
|
type Tenant struct {
|
||||||
metav1.TypeMeta `json:",inline"`
|
metav1.TypeMeta `json:",inline"`
|
||||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
// +optional
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
Spec TenantSpec `json:"spec,omitempty"`
|
Spec TenantSpec `json:"spec"`
|
||||||
Status TenantStatus `json:"status,omitempty"`
|
// +optional
|
||||||
|
Status TenantStatus `json:"status,omitzero"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in *Tenant) Hub() {}
|
func (in *Tenant) Hub() {}
|
||||||
@@ -64,7 +70,9 @@ func (in *Tenant) Hub() {}
|
|||||||
// TenantList contains a list of Tenant.
|
// TenantList contains a list of Tenant.
|
||||||
type TenantList struct {
|
type TenantList struct {
|
||||||
metav1.TypeMeta `json:",inline"`
|
metav1.TypeMeta `json:",inline"`
|
||||||
metav1.ListMeta `json:"metadata,omitempty"`
|
// +optional
|
||||||
|
metav1.ListMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
Items []Tenant `json:"items"`
|
Items []Tenant `json:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,5 +85,5 @@ func (in *Tenant) GetNamespaces() (res []string) {
|
|||||||
|
|
||||||
res = append(res, in.Status.Namespaces...)
|
res = append(res, in.Status.Namespaces...)
|
||||||
|
|
||||||
return
|
return res
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta1
|
package v1beta1
|
||||||
@@ -15,7 +15,6 @@ func (in *Tenant) SetupWebhookWithManager(mgr ctrl.Manager) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctrl.NewWebhookManagedBy(mgr).
|
return ctrl.NewWebhookManagedBy(mgr, in).
|
||||||
For(in).
|
|
||||||
Complete()
|
Complete()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta2
|
package v1beta2
|
||||||
|
|||||||
19
api/v1beta2/capsuleconfiguration_status.go
Normal file
19
api/v1beta2/capsuleconfiguration_status.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1beta2
|
||||||
|
|
||||||
|
import (
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
"github.com/projectcapsule/capsule/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CapsuleConfigurationStatus defines the Capsule configuration status.
|
||||||
|
type CapsuleConfigurationStatus struct {
|
||||||
|
// Last time all caches were invalided
|
||||||
|
LastCacheInvalidation metav1.Time `json:"lastCacheInvalidation,omitempty"`
|
||||||
|
|
||||||
|
// Users which are considered Capsule Users and are bound to the Capsule Tenant construct.
|
||||||
|
Users api.UserListSpec `json:"users,omitempty"`
|
||||||
|
}
|
||||||
@@ -1,19 +1,37 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta2
|
package v1beta2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/projectcapsule/capsule/pkg/api"
|
"github.com/projectcapsule/capsule/pkg/api"
|
||||||
|
"github.com/projectcapsule/capsule/pkg/api/meta"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CapsuleConfigurationSpec defines the Capsule configuration.
|
// CapsuleConfigurationSpec defines the Capsule configuration.
|
||||||
type CapsuleConfigurationSpec struct {
|
type CapsuleConfigurationSpec struct {
|
||||||
// Names of the groups for Capsule users.
|
// Define entities which are considered part of the Capsule construct
|
||||||
// +kubebuilder:default={capsule.clastix.io}
|
// Users not mentioned here will be ignored by Capsule
|
||||||
|
Users api.UserListSpec `json:"users,omitempty"`
|
||||||
|
// Deprecated: use users property instead (https://projectcapsule.dev/docs/operating/setup/configuration/#users)
|
||||||
|
//
|
||||||
|
// Names of the users considered as Capsule users.
|
||||||
|
UserNames []string `json:"userNames,omitempty"`
|
||||||
|
// Deprecated: use users property instead (https://projectcapsule.dev/docs/operating/setup/configuration/#users)
|
||||||
|
//
|
||||||
|
// Names of the groups considered as Capsule users.
|
||||||
UserGroups []string `json:"userGroups,omitempty"`
|
UserGroups []string `json:"userGroups,omitempty"`
|
||||||
|
// Define groups which when found in the request of a user will be ignored by the Capsule
|
||||||
|
// this might be useful if you have one group where all the users are in, but you want to separate administrators from normal users with additional groups.
|
||||||
|
IgnoreUserWithGroups []string `json:"ignoreUserWithGroups,omitempty"`
|
||||||
|
// ServiceAccounts within tenant namespaces can be promoted to owners of the given tenant
|
||||||
|
// this can be achieved by labeling the serviceaccount and then they are considered owners. This can only be done by other owners of the tenant.
|
||||||
|
// However ServiceAccounts which have been promoted to owner can not promote further serviceAccounts.
|
||||||
|
// +kubebuilder:default=false
|
||||||
|
AllowServiceAccountPromotion bool `json:"allowServiceAccountPromotion,omitempty"`
|
||||||
// Enforces the Tenant owner, during Namespace creation, to name it using the selected Tenant name as prefix,
|
// Enforces the Tenant owner, during Namespace creation, to name it using the selected Tenant name as prefix,
|
||||||
// separated by a dash. This is useful to avoid Namespace name collision in a public CaaS environment.
|
// separated by a dash. This is useful to avoid Namespace name collision in a public CaaS environment.
|
||||||
// +kubebuilder:default=false
|
// +kubebuilder:default=false
|
||||||
@@ -23,21 +41,73 @@ type CapsuleConfigurationSpec struct {
|
|||||||
// Allows to set different name rather than the canonical one for the Capsule configuration objects,
|
// Allows to set different name rather than the canonical one for the Capsule configuration objects,
|
||||||
// such as webhook secret or configurations.
|
// such as webhook secret or configurations.
|
||||||
// +kubebuilder:default={TLSSecretName:"capsule-tls",mutatingWebhookConfigurationName:"capsule-mutating-webhook-configuration",validatingWebhookConfigurationName:"capsule-validating-webhook-configuration"}
|
// +kubebuilder:default={TLSSecretName:"capsule-tls",mutatingWebhookConfigurationName:"capsule-mutating-webhook-configuration",validatingWebhookConfigurationName:"capsule-validating-webhook-configuration"}
|
||||||
CapsuleResources CapsuleResources `json:"overrides,omitempty"`
|
// +optional
|
||||||
|
CapsuleResources CapsuleResources `json:"overrides,omitzero"`
|
||||||
// Allows to set the forbidden metadata for the worker nodes that could be patched by a Tenant.
|
// Allows to set the forbidden metadata for the worker nodes that could be patched by a Tenant.
|
||||||
// This applies only if the Tenant has an active NodeSelector, and the Owner have right to patch their nodes.
|
// This applies only if the Tenant has an active NodeSelector, and the Owner have right to patch their nodes.
|
||||||
NodeMetadata *NodeMetadata `json:"nodeMetadata,omitempty"`
|
NodeMetadata *NodeMetadata `json:"nodeMetadata,omitempty"`
|
||||||
// Toggles the TLS reconciler, the controller that is able to generate CA and certificates for the webhooks
|
// Toggles the TLS reconciler, the controller that is able to generate CA and certificates for the webhooks
|
||||||
// when not using an already provided CA and certificate, or when these are managed externally with Vault, or cert-manager.
|
// when not using an already provided CA and certificate, or when these are managed externally with Vault, or cert-manager.
|
||||||
// +kubebuilder:default=true
|
// +kubebuilder:default=false
|
||||||
EnableTLSReconciler bool `json:"enableTLSReconciler"` //nolint:tagliatelle
|
EnableTLSReconciler bool `json:"enableTLSReconciler"` //nolint:tagliatelle
|
||||||
|
// Define entities which can act as Administrators in the capsule construct
|
||||||
|
// These entities are automatically owners for all existing tenants. Meaning they can add namespaces to any tenant. However they must be specific by using the capsule label
|
||||||
|
// for interacting with namespaces. Because if that label is not defined, it's assumed that namespace interaction was not targeted towards a tenant and will therefor
|
||||||
|
// be ignored by capsule.
|
||||||
|
Administrators api.UserListSpec `json:"administrators,omitempty"`
|
||||||
|
// Configuration for dynamic Validating and Mutating Admission webhooks managed by Capsule.
|
||||||
|
Admission DynamicAdmission `json:"admission,omitempty"`
|
||||||
|
// Define Properties for managed ClusterRoles by Capsule
|
||||||
|
// +kubebuilder:default={}
|
||||||
|
RBAC *RBACConfiguration `json:"rbac"`
|
||||||
|
// Define the period of time upon a cache invalidation is executed for all caches.
|
||||||
|
// +kubebuilder:default="24h"
|
||||||
|
CacheInvalidation metav1.Duration `json:"cacheInvalidation"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RBACConfiguration struct {
|
||||||
|
// The ClusterRoles applied for Administrators
|
||||||
|
// +kubebuilder:default={capsule-namespace-deleter}
|
||||||
|
AdministrationClusterRoles []string `json:"administrationClusterRoles,omitempty"`
|
||||||
|
// The ClusterRoles applied for ServiceAccounts which had owner Promotion
|
||||||
|
// +kubebuilder:default={capsule-namespace-provisioner,capsule-namespace-deleter}
|
||||||
|
PromotionClusterRoles []string `json:"promotionClusterRoles,omitempty"`
|
||||||
|
// Name for the ClusterRole required to grant Namespace Deletion permissions.
|
||||||
|
// +kubebuilder:default=capsule-namespace-deleter
|
||||||
|
DeleterClusterRole string `json:"deleter,omitempty"`
|
||||||
|
// Name for the ClusterRole required to grant Namespace Provision permissions.
|
||||||
|
// +kubebuilder:default=capsule-namespace-provisioner
|
||||||
|
ProvisionerClusterRole string `json:"provisioner,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DynamicAdmission struct {
|
||||||
|
// Configure dynamic Mutating Admission for Capsule
|
||||||
|
Mutating DynamicAdmissionConfig `json:"mutating,omitempty"`
|
||||||
|
|
||||||
|
// Configure dynamic Validating Admission for Capsule
|
||||||
|
Validating DynamicAdmissionConfig `json:"validating,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DynamicAdmissionConfig struct {
|
||||||
|
// Name the Admission Webhook
|
||||||
|
Name meta.RFC1123Name `json:"name,omitempty"`
|
||||||
|
// Labels added to the Admission Webhook
|
||||||
|
// +optional
|
||||||
|
Labels map[string]string `json:"labels,omitempty"`
|
||||||
|
// Annotations added to the Admission Webhook
|
||||||
|
// +optional
|
||||||
|
Annotations map[string]string `json:"annotations,omitempty"`
|
||||||
|
// From the upstram struct
|
||||||
|
Client admissionregistrationv1.WebhookClientConfig `json:"client"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type NodeMetadata struct {
|
type NodeMetadata struct {
|
||||||
// Define the labels that a Tenant Owner cannot set for their nodes.
|
// Define the labels that a Tenant Owner cannot set for their nodes.
|
||||||
ForbiddenLabels api.ForbiddenListSpec `json:"forbiddenLabels"`
|
// +optional
|
||||||
|
ForbiddenLabels api.ForbiddenListSpec `json:"forbiddenLabels,omitzero"`
|
||||||
// Define the annotations that a Tenant Owner cannot set for their nodes.
|
// Define the annotations that a Tenant Owner cannot set for their nodes.
|
||||||
ForbiddenAnnotations api.ForbiddenListSpec `json:"forbiddenAnnotations"`
|
// +optional
|
||||||
|
ForbiddenAnnotations api.ForbiddenListSpec `json:"forbiddenAnnotations,omitzero"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CapsuleResources struct {
|
type CapsuleResources struct {
|
||||||
@@ -54,15 +124,21 @@ type CapsuleResources struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// +kubebuilder:object:root=true
|
// +kubebuilder:object:root=true
|
||||||
|
// +kubebuilder:subresource:status
|
||||||
// +kubebuilder:resource:scope=Cluster
|
// +kubebuilder:resource:scope=Cluster
|
||||||
// +kubebuilder:storageversion
|
// +kubebuilder:storageversion
|
||||||
|
|
||||||
// CapsuleConfiguration is the Schema for the Capsule configuration API.
|
// CapsuleConfiguration is the Schema for the Capsule configuration API.
|
||||||
type CapsuleConfiguration struct {
|
type CapsuleConfiguration struct {
|
||||||
metav1.TypeMeta `json:",inline"`
|
metav1.TypeMeta `json:",inline"`
|
||||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
|
||||||
|
|
||||||
Spec CapsuleConfigurationSpec `json:"spec,omitempty"`
|
// +optional
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
|
Spec CapsuleConfigurationSpec `json:"spec"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
Status CapsuleConfigurationStatus `json:"status,omitzero"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +kubebuilder:object:root=true
|
// +kubebuilder:object:root=true
|
||||||
@@ -70,7 +146,8 @@ type CapsuleConfiguration struct {
|
|||||||
// CapsuleConfigurationList contains a list of CapsuleConfiguration.
|
// CapsuleConfigurationList contains a list of CapsuleConfiguration.
|
||||||
type CapsuleConfigurationList struct {
|
type CapsuleConfigurationList struct {
|
||||||
metav1.TypeMeta `json:",inline"`
|
metav1.TypeMeta `json:",inline"`
|
||||||
metav1.ListMeta `json:"metadata,omitempty"`
|
metav1.ListMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
Items []CapsuleConfiguration `json:"items"`
|
Items []CapsuleConfiguration `json:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta2
|
package v1beta2
|
||||||
|
|||||||
12
api/v1beta2/gateway_options.go
Normal file
12
api/v1beta2/gateway_options.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1beta2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/projectcapsule/capsule/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GatewayOptions struct {
|
||||||
|
AllowedClasses *api.DefaultAllowedListSpec `json:"allowedClasses,omitempty"`
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Package v1beta2 contains API Schema definitions for the capsule v1beta2 API group
|
// Package v1beta2 contains API Schema definitions for the capsule v1beta2 API group
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta2
|
package v1beta2
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta2
|
package v1beta2
|
||||||
@@ -11,10 +11,32 @@ type NamespaceOptions struct {
|
|||||||
// +kubebuilder:validation:Minimum=1
|
// +kubebuilder:validation:Minimum=1
|
||||||
// Specifies the maximum number of namespaces allowed for that Tenant. Once the namespace quota assigned to the Tenant has been reached, the Tenant owner cannot create further namespaces. Optional.
|
// Specifies the maximum number of namespaces allowed for that Tenant. Once the namespace quota assigned to the Tenant has been reached, the Tenant owner cannot create further namespaces. Optional.
|
||||||
Quota *int32 `json:"quota,omitempty"`
|
Quota *int32 `json:"quota,omitempty"`
|
||||||
|
// Deprecated: Use additionalMetadataList instead (https://projectcapsule.dev/docs/tenants/metadata/#additionalmetadatalist)
|
||||||
|
//
|
||||||
// Specifies additional labels and annotations the Capsule operator places on any Namespace resource in the Tenant. Optional.
|
// Specifies additional labels and annotations the Capsule operator places on any Namespace resource in the Tenant. Optional.
|
||||||
AdditionalMetadata *api.AdditionalMetadataSpec `json:"additionalMetadata,omitempty"`
|
AdditionalMetadata *api.AdditionalMetadataSpec `json:"additionalMetadata,omitempty"`
|
||||||
|
// Specifies additional labels and annotations the Capsule operator places on any Namespace resource in the Tenant via a list. Optional.
|
||||||
|
AdditionalMetadataList []api.AdditionalMetadataSelectorSpec `json:"additionalMetadataList,omitempty"`
|
||||||
|
// Required Metadata for namespace within this tenant
|
||||||
|
// +optional
|
||||||
|
RequiredMetadata *RequiredMetadata `json:"requiredMetadata,omitzero"`
|
||||||
// Define the labels that a Tenant Owner cannot set for their Namespace resources.
|
// Define the labels that a Tenant Owner cannot set for their Namespace resources.
|
||||||
ForbiddenLabels api.ForbiddenListSpec `json:"forbiddenLabels,omitempty"`
|
// +optional
|
||||||
|
ForbiddenLabels api.ForbiddenListSpec `json:"forbiddenLabels,omitzero"`
|
||||||
// Define the annotations that a Tenant Owner cannot set for their Namespace resources.
|
// Define the annotations that a Tenant Owner cannot set for their Namespace resources.
|
||||||
ForbiddenAnnotations api.ForbiddenListSpec `json:"forbiddenAnnotations,omitempty"`
|
// +optional
|
||||||
|
ForbiddenAnnotations api.ForbiddenListSpec `json:"forbiddenAnnotations,omitzero"`
|
||||||
|
// If enabled only metadata from additionalMetadata is reconciled to the namespaces.
|
||||||
|
//+kubebuilder:default:=false
|
||||||
|
ManagedMetadataOnly bool `json:"managedMetadataOnly,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RequiredMetadata struct {
|
||||||
|
// Labels that must be defined for each namespace
|
||||||
|
// +optional
|
||||||
|
Labels map[string]string `json:"labels,omitzero"`
|
||||||
|
|
||||||
|
// Annotations that must be defined for each namespace
|
||||||
|
// +optional
|
||||||
|
Annotations map[string]string `json:"annotations,omitzero"`
|
||||||
}
|
}
|
||||||
|
|||||||
33
api/v1beta2/namespace_rule_type.go
Normal file
33
api/v1beta2/namespace_rule_type.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1beta2
|
||||||
|
|
||||||
|
import (
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
"github.com/projectcapsule/capsule/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
// +kubebuilder:object:generate=true
|
||||||
|
type NamespaceRule struct {
|
||||||
|
// Enforce these properties via Rules
|
||||||
|
NamespaceRuleBody `json:",inline"`
|
||||||
|
|
||||||
|
// Select namespaces which are going to usese
|
||||||
|
NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:object:generate=true
|
||||||
|
type NamespaceRuleBody struct {
|
||||||
|
// Enforcement Rules applied
|
||||||
|
//+optional
|
||||||
|
Enforce NamespaceRuleEnforceBody `json:"enforce,omitzero"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:object:generate=true
|
||||||
|
type NamespaceRuleEnforceBody struct {
|
||||||
|
// Define registries which are allowed to be used within this tenant
|
||||||
|
// The rules are aggregated, since you can use Regular Expressions the match registry endpoints
|
||||||
|
Registries []api.OCIRegistry `json:"registries,omitempty"`
|
||||||
|
}
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package v1beta2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestOwnerListSpec_FindOwner(t *testing.T) {
|
|
||||||
bla := OwnerSpec{
|
|
||||||
Kind: UserOwner,
|
|
||||||
Name: "bla",
|
|
||||||
ProxyOperations: []ProxySettings{
|
|
||||||
{
|
|
||||||
Kind: IngressClassesProxy,
|
|
||||||
Operations: []ProxyOperation{"Delete"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
bar := OwnerSpec{
|
|
||||||
Kind: GroupOwner,
|
|
||||||
Name: "bar",
|
|
||||||
ProxyOperations: []ProxySettings{
|
|
||||||
{
|
|
||||||
Kind: StorageClassesProxy,
|
|
||||||
Operations: []ProxyOperation{"Delete"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
baz := OwnerSpec{
|
|
||||||
Kind: UserOwner,
|
|
||||||
Name: "baz",
|
|
||||||
ProxyOperations: []ProxySettings{
|
|
||||||
{
|
|
||||||
Kind: StorageClassesProxy,
|
|
||||||
Operations: []ProxyOperation{"Update"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
fim := OwnerSpec{
|
|
||||||
Kind: ServiceAccountOwner,
|
|
||||||
Name: "fim",
|
|
||||||
ProxyOperations: []ProxySettings{
|
|
||||||
{
|
|
||||||
Kind: NodesProxy,
|
|
||||||
Operations: []ProxyOperation{"List"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
bom := OwnerSpec{
|
|
||||||
Kind: GroupOwner,
|
|
||||||
Name: "bom",
|
|
||||||
ProxyOperations: []ProxySettings{
|
|
||||||
{
|
|
||||||
Kind: StorageClassesProxy,
|
|
||||||
Operations: []ProxyOperation{"Delete"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Kind: NodesProxy,
|
|
||||||
Operations: []ProxyOperation{"Delete"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
qip := OwnerSpec{
|
|
||||||
Kind: ServiceAccountOwner,
|
|
||||||
Name: "qip",
|
|
||||||
ProxyOperations: []ProxySettings{
|
|
||||||
{
|
|
||||||
Kind: StorageClassesProxy,
|
|
||||||
Operations: []ProxyOperation{"List", "Delete"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
owners := OwnerListSpec{bom, qip, bla, bar, baz, fim}
|
|
||||||
|
|
||||||
assert.Equal(t, owners.FindOwner("bom", GroupOwner), bom)
|
|
||||||
assert.Equal(t, owners.FindOwner("qip", ServiceAccountOwner), qip)
|
|
||||||
assert.Equal(t, owners.FindOwner("bla", UserOwner), bla)
|
|
||||||
assert.Equal(t, owners.FindOwner("bar", GroupOwner), bar)
|
|
||||||
assert.Equal(t, owners.FindOwner("baz", UserOwner), baz)
|
|
||||||
assert.Equal(t, owners.FindOwner("fim", ServiceAccountOwner), fim)
|
|
||||||
assert.Equal(t, owners.FindOwner("notfound", ServiceAccountOwner), OwnerSpec{})
|
|
||||||
}
|
|
||||||
282
api/v1beta2/resourcepool_func.go
Normal file
282
api/v1beta2/resourcepool_func.go
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1beta2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
|
||||||
|
"github.com/projectcapsule/capsule/pkg/api/meta"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *ResourcePool) GetQuotaName() string {
|
||||||
|
return fmt.Sprintf("capsule-pool-%s", r.GetName())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ResourcePool) AssignNamespaces(namespaces []corev1.Namespace) {
|
||||||
|
var l []string
|
||||||
|
|
||||||
|
for _, ns := range namespaces {
|
||||||
|
if ns.Status.Phase == corev1.NamespaceActive && ns.DeletionTimestamp == nil {
|
||||||
|
l = append(l, ns.GetName())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(l)
|
||||||
|
|
||||||
|
r.Status.NamespaceSize = uint(len(l))
|
||||||
|
r.Status.Namespaces = l
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ResourcePool) AssignClaims() {
|
||||||
|
var size uint
|
||||||
|
|
||||||
|
for _, claims := range r.Status.Claims {
|
||||||
|
for range claims {
|
||||||
|
size++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Status.ClaimSize = size
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ResourcePool) GetClaimFromStatus(cl *ResourcePoolClaim) *ResourcePoolClaimsItem {
|
||||||
|
ns := cl.Namespace
|
||||||
|
|
||||||
|
claims := r.Status.Claims[ns]
|
||||||
|
if claims == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, claim := range claims {
|
||||||
|
if claim.UID == cl.UID {
|
||||||
|
return claim
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ResourcePool) AddClaimToStatus(claim *ResourcePoolClaim) {
|
||||||
|
ns := claim.Namespace
|
||||||
|
|
||||||
|
if r.Status.Claims == nil {
|
||||||
|
r.Status.Claims = ResourcePoolNamespaceClaimsStatus{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Status.Allocation.Claimed == nil {
|
||||||
|
r.Status.Allocation.Claimed = corev1.ResourceList{}
|
||||||
|
}
|
||||||
|
|
||||||
|
claims := r.Status.Claims[ns]
|
||||||
|
if claims == nil {
|
||||||
|
claims = ResourcePoolClaimsList{}
|
||||||
|
}
|
||||||
|
|
||||||
|
scl := &ResourcePoolClaimsItem{
|
||||||
|
NamespacedRFC1123ObjectReferenceWithNamespaceWithUID: meta.NamespacedRFC1123ObjectReferenceWithNamespaceWithUID{
|
||||||
|
UID: claim.UID,
|
||||||
|
Name: meta.RFC1123Name(claim.Name),
|
||||||
|
Namespace: meta.RFC1123SubdomainName(claim.Namespace),
|
||||||
|
},
|
||||||
|
Claims: claim.Spec.ResourceClaims,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to update existing entry if UID matches
|
||||||
|
exists := false
|
||||||
|
|
||||||
|
for i, cl := range claims {
|
||||||
|
if cl.UID == claim.UID {
|
||||||
|
claims[i] = scl
|
||||||
|
|
||||||
|
exists = true
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
claims = append(claims, scl)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Status.Claims[ns] = claims
|
||||||
|
|
||||||
|
r.CalculateClaimedResources()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ResourcePool) RemoveClaimFromStatus(claim *ResourcePoolClaim) {
|
||||||
|
newClaims := ResourcePoolClaimsList{}
|
||||||
|
|
||||||
|
claims, ok := r.Status.Claims[claim.Namespace]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cl := range claims {
|
||||||
|
if cl.UID != claim.UID {
|
||||||
|
newClaims = append(newClaims, cl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Status.Claims[claim.Namespace] = newClaims
|
||||||
|
|
||||||
|
if len(newClaims) == 0 {
|
||||||
|
delete(r.Status.Claims, claim.Namespace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ResourcePool) CalculateClaimedResources() {
|
||||||
|
usage := corev1.ResourceList{}
|
||||||
|
|
||||||
|
for res := range r.Status.Allocation.Hard {
|
||||||
|
usage[res] = resource.MustParse("0")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, claims := range r.Status.Claims {
|
||||||
|
for _, claim := range claims {
|
||||||
|
for resourceName, qt := range claim.Claims {
|
||||||
|
amount, exists := usage[resourceName]
|
||||||
|
if !exists {
|
||||||
|
amount = resource.MustParse("0")
|
||||||
|
}
|
||||||
|
|
||||||
|
amount.Add(qt)
|
||||||
|
usage[resourceName] = amount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Status.Allocation.Claimed = usage
|
||||||
|
|
||||||
|
r.CalculateAvailableResources()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ResourcePool) CalculateAvailableResources() {
|
||||||
|
available := corev1.ResourceList{}
|
||||||
|
|
||||||
|
for res, qt := range r.Status.Allocation.Hard {
|
||||||
|
amount, exists := r.Status.Allocation.Claimed[res]
|
||||||
|
if exists {
|
||||||
|
qt.Sub(amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
available[res] = qt
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Status.Allocation.Available = available
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ResourcePool) CanClaimFromPool(claim corev1.ResourceList) []error {
|
||||||
|
claimable := r.GetAvailableClaimableResources()
|
||||||
|
errs := []error{}
|
||||||
|
|
||||||
|
for resourceName, req := range claim {
|
||||||
|
available, exists := claimable[resourceName]
|
||||||
|
if !exists || available.IsZero() || available.Cmp(req) < 0 {
|
||||||
|
errs = append(errs, errors.New("not enough resources"+string(resourceName)+"available"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ResourcePool) GetAvailableClaimableResources() corev1.ResourceList {
|
||||||
|
hard := r.Status.Allocation.Hard.DeepCopy()
|
||||||
|
|
||||||
|
for resourceName, qt := range hard {
|
||||||
|
claimed, exists := r.Status.Allocation.Claimed[resourceName]
|
||||||
|
if !exists {
|
||||||
|
claimed = resource.MustParse("0")
|
||||||
|
}
|
||||||
|
|
||||||
|
qt.Sub(claimed)
|
||||||
|
|
||||||
|
hard[resourceName] = qt
|
||||||
|
}
|
||||||
|
|
||||||
|
return hard
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the Hard specification for the resourcequotas
|
||||||
|
// This takes into account the default resources being used. However they don't count towards the claim usage
|
||||||
|
// This can be changed in the future, the default is not calculated as usage because this might interrupt the namespace management
|
||||||
|
// As we would need to verify if a new namespace with it's defaults still has place in the Pool. Same with attempting to join existing namespaces.
|
||||||
|
func (r *ResourcePool) GetResourceQuotaHardResources(namespace string) corev1.ResourceList {
|
||||||
|
_, claimed := r.GetNamespaceClaims(namespace)
|
||||||
|
|
||||||
|
for resourceName, amount := range claimed {
|
||||||
|
if amount.IsZero() {
|
||||||
|
delete(claimed, resourceName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only Consider Default, when enabled
|
||||||
|
for resourceName, amount := range r.Spec.Defaults {
|
||||||
|
usedValue := claimed[resourceName]
|
||||||
|
usedValue.Add(amount)
|
||||||
|
|
||||||
|
claimed[resourceName] = usedValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return claimed
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the total amount of claimed resources for a namespace.
|
||||||
|
func (r *ResourcePool) GetNamespaceClaims(namespace string) (claims map[string]*ResourcePoolClaimsItem, claimedResources corev1.ResourceList) {
|
||||||
|
claimedResources = corev1.ResourceList{}
|
||||||
|
claims = map[string]*ResourcePoolClaimsItem{}
|
||||||
|
|
||||||
|
// First, check if quota exists in the status
|
||||||
|
for ns, cl := range r.Status.Claims {
|
||||||
|
if ns != namespace {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, claim := range cl {
|
||||||
|
for resourceName, claimed := range claim.Claims {
|
||||||
|
usedValue, usedExists := claimedResources[resourceName]
|
||||||
|
if !usedExists {
|
||||||
|
usedValue = resource.MustParse("0") // Default to zero if no used value is found
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combine with claim
|
||||||
|
usedValue.Add(claimed)
|
||||||
|
claimedResources[resourceName] = usedValue
|
||||||
|
}
|
||||||
|
|
||||||
|
claims[string(claim.UID)] = claim
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return claims, claimedResources
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate usage for each namespace.
|
||||||
|
func (r *ResourcePool) GetClaimedByNamespaceClaims() (claims map[string]corev1.ResourceList) {
|
||||||
|
claims = map[string]corev1.ResourceList{}
|
||||||
|
|
||||||
|
// First, check if quota exists in the status
|
||||||
|
for ns, cl := range r.Status.Claims {
|
||||||
|
claims[ns] = corev1.ResourceList{}
|
||||||
|
nsScope := claims[ns]
|
||||||
|
|
||||||
|
for _, claim := range cl {
|
||||||
|
for resourceName, claimed := range claim.Claims {
|
||||||
|
usedValue, usedExists := nsScope[resourceName]
|
||||||
|
if !usedExists {
|
||||||
|
usedValue = resource.MustParse("0")
|
||||||
|
}
|
||||||
|
|
||||||
|
usedValue.Add(claimed)
|
||||||
|
nsScope[resourceName] = usedValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return claims
|
||||||
|
}
|
||||||
318
api/v1beta2/resourcepool_func_test.go
Normal file
318
api/v1beta2/resourcepool_func_test.go
Normal file
@@ -0,0 +1,318 @@
|
|||||||
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1beta2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
|
||||||
|
"github.com/projectcapsule/capsule/pkg/api/meta"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetClaimFromStatus(t *testing.T) {
|
||||||
|
ns := "test-namespace"
|
||||||
|
testUID := types.UID("test-uid")
|
||||||
|
otherUID := types.UID("wrong-uid")
|
||||||
|
|
||||||
|
claim := &ResourcePoolClaim{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "claim-a",
|
||||||
|
Namespace: ns,
|
||||||
|
UID: testUID,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pool := &ResourcePool{
|
||||||
|
Status: ResourcePoolStatus{
|
||||||
|
Claims: ResourcePoolNamespaceClaimsStatus{
|
||||||
|
ns: {
|
||||||
|
&ResourcePoolClaimsItem{
|
||||||
|
NamespacedRFC1123ObjectReferenceWithNamespaceWithUID: meta.NamespacedRFC1123ObjectReferenceWithNamespaceWithUID{
|
||||||
|
UID: testUID,
|
||||||
|
},
|
||||||
|
Claims: corev1.ResourceList{
|
||||||
|
corev1.ResourceCPU: resource.MustParse("500m"),
|
||||||
|
corev1.ResourceMemory: resource.MustParse("256Mi"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("returns matching claim", func(t *testing.T) {
|
||||||
|
found := pool.GetClaimFromStatus(claim)
|
||||||
|
assert.NotNil(t, found)
|
||||||
|
assert.Equal(t, testUID, found.UID)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("returns nil if UID doesn't match", func(t *testing.T) {
|
||||||
|
claimWrongUID := *claim
|
||||||
|
claimWrongUID.UID = otherUID
|
||||||
|
|
||||||
|
found := pool.GetClaimFromStatus(&claimWrongUID)
|
||||||
|
assert.Nil(t, found)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("returns nil if namespace has no claims", func(t *testing.T) {
|
||||||
|
claimWrongNS := *claim
|
||||||
|
claimWrongNS.Namespace = "other-ns"
|
||||||
|
|
||||||
|
found := pool.GetClaimFromStatus(&claimWrongNS)
|
||||||
|
assert.Nil(t, found)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeResourceList(cpu, memory string) corev1.ResourceList {
|
||||||
|
return corev1.ResourceList{
|
||||||
|
corev1.ResourceLimitsCPU: resource.MustParse(cpu),
|
||||||
|
corev1.ResourceLimitsMemory: resource.MustParse(memory),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeClaim(name, ns string, uid types.UID, res corev1.ResourceList) *ResourcePoolClaim {
|
||||||
|
return &ResourcePoolClaim{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: name,
|
||||||
|
Namespace: ns,
|
||||||
|
UID: uid,
|
||||||
|
},
|
||||||
|
Spec: ResourcePoolClaimSpec{
|
||||||
|
ResourceClaims: res,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAssignNamespaces(t *testing.T) {
|
||||||
|
pool := &ResourcePool{}
|
||||||
|
|
||||||
|
namespaces := []corev1.Namespace{
|
||||||
|
{ObjectMeta: metav1.ObjectMeta{Name: "active-ns"}, Status: corev1.NamespaceStatus{Phase: corev1.NamespaceActive}},
|
||||||
|
{ObjectMeta: metav1.ObjectMeta{Name: "terminating-ns", DeletionTimestamp: &metav1.Time{}}, Status: corev1.NamespaceStatus{Phase: corev1.NamespaceTerminating}},
|
||||||
|
}
|
||||||
|
|
||||||
|
pool.AssignNamespaces(namespaces)
|
||||||
|
|
||||||
|
assert.Equal(t, uint(1), pool.Status.NamespaceSize)
|
||||||
|
assert.Equal(t, []string{"active-ns"}, pool.Status.Namespaces)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAssignClaims(t *testing.T) {
|
||||||
|
pool := &ResourcePool{
|
||||||
|
Status: ResourcePoolStatus{
|
||||||
|
Claims: ResourcePoolNamespaceClaimsStatus{
|
||||||
|
"ns": {
|
||||||
|
&ResourcePoolClaimsItem{},
|
||||||
|
&ResourcePoolClaimsItem{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
pool.AssignClaims()
|
||||||
|
|
||||||
|
assert.Equal(t, uint(2), pool.Status.ClaimSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddRemoveClaimToStatus(t *testing.T) {
|
||||||
|
pool := &ResourcePool{}
|
||||||
|
|
||||||
|
claim := makeClaim("claim-1", "ns", "uid-1", makeResourceList("1", "1Gi"))
|
||||||
|
pool.AddClaimToStatus(claim)
|
||||||
|
|
||||||
|
stored := pool.GetClaimFromStatus(claim)
|
||||||
|
|
||||||
|
assert.NotNil(t, stored)
|
||||||
|
assert.Equal(t, meta.RFC1123Name("claim-1"), stored.Name)
|
||||||
|
|
||||||
|
pool.RemoveClaimFromStatus(claim)
|
||||||
|
assert.Nil(t, pool.GetClaimFromStatus(claim))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCalculateResources(t *testing.T) {
|
||||||
|
pool := &ResourcePool{
|
||||||
|
Status: ResourcePoolStatus{
|
||||||
|
Allocation: ResourcePoolQuotaStatus{
|
||||||
|
Hard: corev1.ResourceList{
|
||||||
|
corev1.ResourceLimitsCPU: resource.MustParse("2"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Claims: ResourcePoolNamespaceClaimsStatus{
|
||||||
|
"ns": {
|
||||||
|
&ResourcePoolClaimsItem{
|
||||||
|
Claims: corev1.ResourceList{
|
||||||
|
corev1.ResourceLimitsCPU: resource.MustParse("1"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pool.CalculateClaimedResources()
|
||||||
|
|
||||||
|
actualClaimed := pool.Status.Allocation.Claimed[corev1.ResourceLimitsCPU]
|
||||||
|
actualAvailable := pool.Status.Allocation.Available[corev1.ResourceLimitsCPU]
|
||||||
|
|
||||||
|
assert.Equal(t, 0, (&actualClaimed).Cmp(resource.MustParse("1")))
|
||||||
|
assert.Equal(t, 0, (&actualAvailable).Cmp(resource.MustParse("1")))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCanClaimFromPool(t *testing.T) {
|
||||||
|
pool := &ResourcePool{
|
||||||
|
Status: ResourcePoolStatus{
|
||||||
|
Allocation: ResourcePoolQuotaStatus{
|
||||||
|
Hard: corev1.ResourceList{
|
||||||
|
corev1.ResourceLimitsMemory: resource.MustParse("1Gi"),
|
||||||
|
},
|
||||||
|
Claimed: corev1.ResourceList{
|
||||||
|
corev1.ResourceLimitsMemory: resource.MustParse("512Mi"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
errs := pool.CanClaimFromPool(corev1.ResourceList{
|
||||||
|
corev1.ResourceLimitsMemory: resource.MustParse("1Gi"),
|
||||||
|
})
|
||||||
|
assert.Len(t, errs, 1)
|
||||||
|
|
||||||
|
errs = pool.CanClaimFromPool(corev1.ResourceList{
|
||||||
|
corev1.ResourceLimitsMemory: resource.MustParse("500Mi"),
|
||||||
|
})
|
||||||
|
assert.Len(t, errs, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetResourceQuotaHardResources(t *testing.T) {
|
||||||
|
pool := &ResourcePool{
|
||||||
|
Spec: ResourcePoolSpec{
|
||||||
|
Defaults: corev1.ResourceList{
|
||||||
|
corev1.ResourceLimitsCPU: resource.MustParse("1"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Status: ResourcePoolStatus{
|
||||||
|
Claims: ResourcePoolNamespaceClaimsStatus{
|
||||||
|
"ns": {
|
||||||
|
&ResourcePoolClaimsItem{
|
||||||
|
Claims: corev1.ResourceList{
|
||||||
|
corev1.ResourceLimitsCPU: resource.MustParse("1"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
res := pool.GetResourceQuotaHardResources("ns")
|
||||||
|
actual := res[corev1.ResourceLimitsCPU]
|
||||||
|
assert.Equal(t, 0, (&actual).Cmp(resource.MustParse("2")))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetNamespaceClaims(t *testing.T) {
|
||||||
|
pool := &ResourcePool{
|
||||||
|
Status: ResourcePoolStatus{
|
||||||
|
Claims: ResourcePoolNamespaceClaimsStatus{
|
||||||
|
"ns": {
|
||||||
|
&ResourcePoolClaimsItem{
|
||||||
|
NamespacedRFC1123ObjectReferenceWithNamespaceWithUID: meta.NamespacedRFC1123ObjectReferenceWithNamespaceWithUID{UID: "uid1"},
|
||||||
|
Claims: corev1.ResourceList{
|
||||||
|
corev1.ResourceLimitsCPU: resource.MustParse("1"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
claims, res := pool.GetNamespaceClaims("ns")
|
||||||
|
assert.Contains(t, claims, "uid1")
|
||||||
|
actual := res[corev1.ResourceLimitsCPU]
|
||||||
|
assert.Equal(t, 0, (&actual).Cmp(resource.MustParse("1")))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetClaimedByNamespaceClaims(t *testing.T) {
|
||||||
|
pool := &ResourcePool{
|
||||||
|
Status: ResourcePoolStatus{
|
||||||
|
Claims: ResourcePoolNamespaceClaimsStatus{
|
||||||
|
"ns1": {
|
||||||
|
&ResourcePoolClaimsItem{
|
||||||
|
Claims: makeResourceList("1", "1Gi"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
result := pool.GetClaimedByNamespaceClaims()
|
||||||
|
actualCPU := result["ns1"][corev1.ResourceLimitsCPU]
|
||||||
|
actualMem := result["ns1"][corev1.ResourceLimitsMemory]
|
||||||
|
|
||||||
|
assert.Equal(t, 0, (&actualCPU).Cmp(resource.MustParse("1")))
|
||||||
|
assert.Equal(t, 0, (&actualMem).Cmp(resource.MustParse("1Gi")))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsBoundToResourcePool_2(t *testing.T) {
|
||||||
|
t.Run("bound to resource pool (Assigned=True)", func(t *testing.T) {
|
||||||
|
claim := &ResourcePoolClaim{
|
||||||
|
Status: ResourcePoolClaimStatus{
|
||||||
|
Conditions: meta.ConditionList{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, false, claim.IsBoundInResourcePool())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("not bound - wrong condition type", func(t *testing.T) {
|
||||||
|
claim := &ResourcePoolClaim{
|
||||||
|
Status: ResourcePoolClaimStatus{
|
||||||
|
Conditions: meta.ConditionList{
|
||||||
|
meta.Condition{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cond := meta.NewAssignedCondition(claim)
|
||||||
|
cond.Status = metav1.ConditionFalse
|
||||||
|
claim.Status.Conditions.UpdateConditionByType(cond)
|
||||||
|
|
||||||
|
assert.Equal(t, false, claim.IsBoundInResourcePool())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("not bound - condition not true", func(t *testing.T) {
|
||||||
|
claim := &ResourcePoolClaim{
|
||||||
|
Status: ResourcePoolClaimStatus{
|
||||||
|
Conditions: meta.ConditionList{
|
||||||
|
meta.Condition{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cond := meta.NewBoundCondition(claim)
|
||||||
|
cond.Status = metav1.ConditionFalse
|
||||||
|
claim.Status.Conditions.UpdateConditionByType(cond)
|
||||||
|
|
||||||
|
assert.Equal(t, false, claim.IsBoundInResourcePool())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("not bound - condition not true", func(t *testing.T) {
|
||||||
|
claim := &ResourcePoolClaim{
|
||||||
|
Status: ResourcePoolClaimStatus{
|
||||||
|
Conditions: meta.ConditionList{
|
||||||
|
meta.Condition{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cond := meta.NewBoundCondition(claim)
|
||||||
|
cond.Status = metav1.ConditionTrue
|
||||||
|
claim.Status.Conditions.UpdateConditionByType(cond)
|
||||||
|
|
||||||
|
assert.Equal(t, true, claim.IsBoundInResourcePool())
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
70
api/v1beta2/resourcepool_status.go
Normal file
70
api/v1beta2/resourcepool_status.go
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1beta2
|
||||||
|
|
||||||
|
import (
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
|
||||||
|
"github.com/projectcapsule/capsule/pkg/api"
|
||||||
|
"github.com/projectcapsule/capsule/pkg/api/meta"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GlobalResourceQuotaStatus defines the observed state of GlobalResourceQuota.
|
||||||
|
type ResourcePoolStatus struct {
|
||||||
|
// How many namespaces are considered
|
||||||
|
// +kubebuilder:default=0
|
||||||
|
NamespaceSize uint `json:"namespaceCount,omitempty"`
|
||||||
|
// Amount of claims
|
||||||
|
// +kubebuilder:default=0
|
||||||
|
ClaimSize uint `json:"claimCount,omitempty"`
|
||||||
|
// Namespaces which are considered for claims
|
||||||
|
Namespaces []string `json:"namespaces,omitempty"`
|
||||||
|
// Tracks the quotas for the Resource.
|
||||||
|
// +optional
|
||||||
|
Claims ResourcePoolNamespaceClaimsStatus `json:"claims,omitzero"`
|
||||||
|
// Tracks the Usage from Claimed against what has been granted from the pool
|
||||||
|
// +optional
|
||||||
|
Allocation ResourcePoolQuotaStatus `json:"allocation,omitzero"`
|
||||||
|
// Exhaustions from claims associated with the pool
|
||||||
|
Exhaustions map[string]api.PoolExhaustionResource `json:"exhaustions,omitempty"`
|
||||||
|
// Conditions for the resource claim
|
||||||
|
Conditions meta.ConditionList `json:"conditions,omitzero"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResourcePoolNamespaceClaimsStatus map[string]ResourcePoolClaimsList
|
||||||
|
|
||||||
|
type ResourcePoolQuotaStatus struct {
|
||||||
|
// Hard is the set of enforced hard limits for each named resource.
|
||||||
|
// More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/
|
||||||
|
// +optional
|
||||||
|
Hard corev1.ResourceList `json:"hard,omitempty" protobuf:"bytes,1,rep,name=hard,casttype=ResourceList,castkey=ResourceName"`
|
||||||
|
// Used is the current observed total usage of the resource in the namespace.
|
||||||
|
// +optional
|
||||||
|
Claimed corev1.ResourceList `json:"used,omitempty" protobuf:"bytes,2,rep,name=used,casttype=ResourceList,castkey=ResourceName"`
|
||||||
|
// Used to track the usage of the resource in the pool (diff hard - claimed). May be used for further automation
|
||||||
|
// +optional
|
||||||
|
Available corev1.ResourceList `json:"available,omitempty" protobuf:"bytes,2,rep,name=available,casttype=ResourceList,castkey=ResourceName"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResourcePoolClaimsList []*ResourcePoolClaimsItem
|
||||||
|
|
||||||
|
func (r *ResourcePoolClaimsList) GetClaimByUID(uid types.UID) *ResourcePoolClaimsItem {
|
||||||
|
for _, claim := range *r {
|
||||||
|
if claim.UID == uid {
|
||||||
|
return claim
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResourceQuotaClaimStatus defines the observed state of ResourceQuotaClaim.
|
||||||
|
type ResourcePoolClaimsItem struct {
|
||||||
|
// Reference to the GlobalQuota being claimed from
|
||||||
|
meta.NamespacedRFC1123ObjectReferenceWithNamespaceWithUID `json:",inline"`
|
||||||
|
|
||||||
|
// Claimed resources
|
||||||
|
Claims corev1.ResourceList `json:"claims,omitempty"`
|
||||||
|
}
|
||||||
87
api/v1beta2/resourcepool_types.go
Normal file
87
api/v1beta2/resourcepool_types.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1beta2
|
||||||
|
|
||||||
|
import (
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
"github.com/projectcapsule/capsule/pkg/runtime/selectors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ResourcePoolSpec.
|
||||||
|
type ResourcePoolSpec struct {
|
||||||
|
// Selector to match the namespaces that should be managed by the GlobalResourceQuota
|
||||||
|
Selectors []selectors.NamespaceSelector `json:"selectors,omitempty"`
|
||||||
|
// Define the resourcequota served by this resourcepool.
|
||||||
|
Quota corev1.ResourceQuotaSpec `json:"quota"`
|
||||||
|
// The Defaults given for each namespace, the default is not counted towards the total allocation
|
||||||
|
// When you use claims it's recommended to provision Defaults as the prevent the scheduling of any resources
|
||||||
|
// +optional
|
||||||
|
Defaults corev1.ResourceList `json:"defaults,omitzero"`
|
||||||
|
// Additional Configuration
|
||||||
|
//+kubebuilder:default:={}
|
||||||
|
// +optional
|
||||||
|
Config ResourcePoolSpecConfiguration `json:"config,omitzero"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResourcePoolSpecConfiguration struct {
|
||||||
|
// With this option all resources which can be allocated are set to 0 for the resourcequota defaults. (Default false)
|
||||||
|
// +kubebuilder:default=false
|
||||||
|
DefaultsAssignZero *bool `json:"defaultsZero,omitempty"`
|
||||||
|
// Claims are queued whenever they are allocated to a pool. A pool tries to allocate claims in order based on their
|
||||||
|
// creation date. But no matter their creation time, if a claim is requesting too much resources it's put into the queue
|
||||||
|
// but if a lower priority claim still has enough space in the available resources, it will be able to claim them. Eventough
|
||||||
|
// it's priority was lower
|
||||||
|
// Enabling this option respects to Order. Meaning the Creationtimestamp matters and if a resource is put into the queue, no
|
||||||
|
// other claim can claim the same resources with lower priority. (Default false)
|
||||||
|
// +kubebuilder:default=false
|
||||||
|
OrderedQueue *bool `json:"orderedQueue,omitempty"`
|
||||||
|
// When a resourcepool is deleted, the resourceclaims bound to it are disassociated from the resourcepool but not deleted.
|
||||||
|
// By Enabling this option, the resourceclaims will be deleted when the resourcepool is deleted, if they are in bound state. (Default false)
|
||||||
|
// +kubebuilder:default=false
|
||||||
|
DeleteBoundResources *bool `json:"deleteBoundResources,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:object:root=true
|
||||||
|
// +kubebuilder:subresource:status
|
||||||
|
// +kubebuilder:resource:scope=Cluster,shortName=quotapool
|
||||||
|
// +kubebuilder:printcolumn:name="Claims",type="integer",JSONPath=".status.claimCount",description="The total amount of Claims bound"
|
||||||
|
// +kubebuilder:printcolumn:name="Namespaces",type="integer",JSONPath=".status.namespaceCount",description="The total amount of Namespaces considered"
|
||||||
|
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description="Reconcile Status"
|
||||||
|
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description="Reconcile Message"
|
||||||
|
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Age"
|
||||||
|
|
||||||
|
// Resourcepools allows you to define a set of resources as known from ResoureQuotas. The Resourcepools are defined at cluster-scope an should
|
||||||
|
// be administrated by cluster-administrators. However they create an interface, where cluster-administrators can define
|
||||||
|
// from which namespaces resources from a Resourcepool can be claimed. The claiming is done via a namespaced CRD called ResourcePoolClaim. Then
|
||||||
|
// it's up the group of users within these namespaces, to manage the resources they consume per namespace. Each Resourcepool provisions a ResourceQuotainto all the selected namespaces. Then essentially the ResourcePoolClaims, when they can be assigned to the ResourcePool stack resources on top of that
|
||||||
|
// ResourceQuota based on the namspace, where the ResourcePoolClaim was made from.
|
||||||
|
type ResourcePool struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
|
Spec ResourcePoolSpec `json:"spec"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
Status ResourcePoolStatus `json:"status,omitzero"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:object:root=true
|
||||||
|
|
||||||
|
// ResourcePoolList contains a list of ResourcePool.
|
||||||
|
type ResourcePoolList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
metav1.ListMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
|
Items []ResourcePool `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SchemeBuilder.Register(&ResourcePool{}, &ResourcePoolList{})
|
||||||
|
}
|
||||||
61
api/v1beta2/resourcepoolclaim_func.go
Normal file
61
api/v1beta2/resourcepoolclaim_func.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1beta2
|
||||||
|
|
||||||
|
import (
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
"github.com/projectcapsule/capsule/pkg/api/meta"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Indicate the claim is bound to a resource pool.
|
||||||
|
func (r *ResourcePoolClaim) IsExhaustedInResourcePool() bool {
|
||||||
|
condition := r.Status.Conditions.GetConditionByType(meta.ExhaustedCondition)
|
||||||
|
|
||||||
|
if condition == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if condition.Status == metav1.ConditionTrue {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ResourcePoolClaim) IsAssignedInResourcePool() bool {
|
||||||
|
condition := r.Status.Conditions.GetConditionByType(meta.AssignedCondition)
|
||||||
|
|
||||||
|
if condition == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if condition.Status == metav1.ConditionTrue {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ResourcePoolClaim) IsBoundInResourcePool() bool {
|
||||||
|
condition := r.Status.Conditions.GetConditionByType(meta.BoundCondition)
|
||||||
|
|
||||||
|
if condition == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if condition.Status == metav1.ConditionTrue {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ResourcePoolClaim) GetPool() string {
|
||||||
|
if name := string(r.Status.Pool.Name); name != "" {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.Spec.Pool
|
||||||
|
}
|
||||||
171
api/v1beta2/resourcepoolclaim_func_test.go
Normal file
171
api/v1beta2/resourcepoolclaim_func_test.go
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1beta2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
"github.com/projectcapsule/capsule/pkg/api/meta"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIsBoundToResourcePool(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
claim ResourcePoolClaim
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "bound to resource pool (Assigned=True)",
|
||||||
|
claim: ResourcePoolClaim{
|
||||||
|
Status: ResourcePoolClaimStatus{
|
||||||
|
Conditions: meta.ConditionList{
|
||||||
|
meta.Condition{
|
||||||
|
Type: meta.BoundCondition,
|
||||||
|
Status: metav1.ConditionTrue,
|
||||||
|
Reason: meta.SucceededReason,
|
||||||
|
Message: "reconciled",
|
||||||
|
LastTransitionTime: metav1.Now(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "not bound - wrong condition type",
|
||||||
|
claim: ResourcePoolClaim{
|
||||||
|
Status: ResourcePoolClaimStatus{
|
||||||
|
Conditions: meta.ConditionList{
|
||||||
|
meta.Condition{
|
||||||
|
Type: meta.AssignedCondition,
|
||||||
|
Status: metav1.ConditionTrue,
|
||||||
|
Reason: meta.SucceededReason,
|
||||||
|
Message: "reconciled",
|
||||||
|
LastTransitionTime: metav1.Now(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "not bound - status not true",
|
||||||
|
claim: ResourcePoolClaim{
|
||||||
|
Status: ResourcePoolClaimStatus{
|
||||||
|
Conditions: meta.ConditionList{
|
||||||
|
meta.Condition{
|
||||||
|
Type: meta.AssignedCondition,
|
||||||
|
Status: metav1.ConditionTrue,
|
||||||
|
Reason: meta.SucceededReason,
|
||||||
|
Message: "reconciled",
|
||||||
|
LastTransitionTime: metav1.Now(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "not bound - empty condition",
|
||||||
|
claim: ResourcePoolClaim{
|
||||||
|
Status: ResourcePoolClaimStatus{},
|
||||||
|
},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
actual := tt.claim.IsBoundInResourcePool()
|
||||||
|
assert.Equal(t, tt.expected, actual)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetPool(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
claim ResourcePoolClaim
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "returns status pool name when set",
|
||||||
|
claim: ResourcePoolClaim{
|
||||||
|
Spec: ResourcePoolClaimSpec{
|
||||||
|
Pool: "spec-pool",
|
||||||
|
},
|
||||||
|
Status: ResourcePoolClaimStatus{
|
||||||
|
Pool: meta.LocalRFC1123ObjectReferenceWithUID{
|
||||||
|
Name: meta.RFC1123Name("status-pool"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: "status-pool",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "falls back to spec pool when status pool name is empty",
|
||||||
|
claim: ResourcePoolClaim{
|
||||||
|
Spec: ResourcePoolClaimSpec{
|
||||||
|
Pool: "spec-pool",
|
||||||
|
},
|
||||||
|
Status: ResourcePoolClaimStatus{
|
||||||
|
Pool: meta.LocalRFC1123ObjectReferenceWithUID{
|
||||||
|
Name: meta.RFC1123Name(""),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: "spec-pool",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "falls back to spec pool when status pool struct is zero-value",
|
||||||
|
claim: ResourcePoolClaim{
|
||||||
|
Spec: ResourcePoolClaimSpec{
|
||||||
|
Pool: "spec-pool",
|
||||||
|
},
|
||||||
|
Status: ResourcePoolClaimStatus{
|
||||||
|
Pool: meta.LocalRFC1123ObjectReferenceWithUID{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: "spec-pool",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "returns empty when both status and spec are empty",
|
||||||
|
claim: ResourcePoolClaim{
|
||||||
|
Spec: ResourcePoolClaimSpec{
|
||||||
|
Pool: "",
|
||||||
|
},
|
||||||
|
Status: ResourcePoolClaimStatus{
|
||||||
|
Pool: meta.LocalRFC1123ObjectReferenceWithUID{
|
||||||
|
Name: meta.RFC1123Name(""),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "status wins even if spec differs",
|
||||||
|
claim: ResourcePoolClaim{
|
||||||
|
Spec: ResourcePoolClaimSpec{
|
||||||
|
Pool: "spec-pool",
|
||||||
|
},
|
||||||
|
Status: ResourcePoolClaimStatus{
|
||||||
|
Pool: meta.LocalRFC1123ObjectReferenceWithUID{
|
||||||
|
Name: meta.RFC1123Name("status-pool"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: "status-pool",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
actual := tt.claim.GetPool()
|
||||||
|
assert.Equal(t, tt.expected, actual)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
72
api/v1beta2/resourcepoolclaim_types.go
Normal file
72
api/v1beta2/resourcepoolclaim_types.go
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1beta2
|
||||||
|
|
||||||
|
import (
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
"github.com/projectcapsule/capsule/pkg/api/meta"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ResourcePoolClaimSpec struct {
|
||||||
|
// If there's the possability to claim from multiple global Quotas
|
||||||
|
// You must be specific about which one you want to claim resources from
|
||||||
|
// Once bound to a ResourcePool, this field is immutable
|
||||||
|
Pool string `json:"pool"`
|
||||||
|
// Amount which should be claimed for the resourcequota
|
||||||
|
ResourceClaims corev1.ResourceList `json:"claim"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResourceQuotaClaimStatus defines the observed state of ResourceQuotaClaim.
|
||||||
|
type ResourcePoolClaimStatus struct {
|
||||||
|
// Reference to the GlobalQuota being claimed from
|
||||||
|
// +optional
|
||||||
|
Pool meta.LocalRFC1123ObjectReferenceWithUID `json:"pool,omitzero"`
|
||||||
|
// Deprecated: Use Conditions
|
||||||
|
//
|
||||||
|
// +optional
|
||||||
|
Condition metav1.Condition `json:"condition,omitzero"`
|
||||||
|
// Conditions for the resource claim
|
||||||
|
Conditions meta.ConditionList `json:"conditions,omitzero"`
|
||||||
|
// Tracks the Usage from Claimed from this claim and available resources
|
||||||
|
// +optional
|
||||||
|
Allocation ResourcePoolQuotaStatus `json:"allocation,omitzero"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:object:root=true
|
||||||
|
// +kubebuilder:subresource:status
|
||||||
|
// +kubebuilder:printcolumn:name="Pool",type="string",JSONPath=".status.pool.name",description="The ResourcePool being claimed from"
|
||||||
|
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description="Ready Status"
|
||||||
|
// +kubebuilder:printcolumn:name="Message",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description="Ready Message"
|
||||||
|
// +kubebuilder:printcolumn:name="Bound",type="string",JSONPath=".status.conditions[?(@.type==\"Bound\")].status",description="Bound Status"
|
||||||
|
// +kubebuilder:printcolumn:name="Reason",type="string",JSONPath=".status.conditions[?(@.type==\"Bound\")].message",description="Bound Message"
|
||||||
|
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""
|
||||||
|
// ResourcePoolClaim is the Schema for the resourcepoolclaims API.
|
||||||
|
type ResourcePoolClaim struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
|
Spec ResourcePoolClaimSpec `json:"spec"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
Status ResourcePoolClaimStatus `json:"status,omitzero"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:object:root=true
|
||||||
|
// ResourceQuotaClaimList contains a list of ResourceQuotaClaim.
|
||||||
|
type ResourcePoolClaimList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
metav1.ListMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
|
Items []ResourcePoolClaim `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SchemeBuilder.Register(&ResourcePoolClaim{}, &ResourcePoolClaimList{})
|
||||||
|
}
|
||||||
44
api/v1beta2/rule_status_type.go
Normal file
44
api/v1beta2/rule_status_type.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1beta2
|
||||||
|
|
||||||
|
import (
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// +kubebuilder:object:root=true
|
||||||
|
// +kubebuilder:storageversion
|
||||||
|
// +kubebuilder:subresource:status
|
||||||
|
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Age"
|
||||||
|
type RuleStatus struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
Status RuleStatusSpec `json:"status,omitzero"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:object:root=true
|
||||||
|
|
||||||
|
// RuleStatusList contains a list of RuleStatus.
|
||||||
|
type RuleStatusList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ListMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
|
Items []RuleStatus `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SchemeBuilder.Register(&RuleStatus{}, &RuleStatusList{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// RuleStatus contains the accumulated rules applying to namespace it's deployed in.
|
||||||
|
// +kubebuilder:object:generate=true
|
||||||
|
type RuleStatusSpec struct {
|
||||||
|
// Managed Enforcement properties per Namespace (aggregated from rules)
|
||||||
|
//+optional
|
||||||
|
Rule NamespaceRuleBody `json:"rule,omitzero"`
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta2
|
package v1beta2
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta2
|
package v1beta2
|
||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
|
|
||||||
capsulev1beta1 "github.com/projectcapsule/capsule/api/v1beta1"
|
capsulev1beta1 "github.com/projectcapsule/capsule/api/v1beta1"
|
||||||
"github.com/projectcapsule/capsule/pkg/api"
|
"github.com/projectcapsule/capsule/pkg/api"
|
||||||
|
"github.com/projectcapsule/capsule/pkg/api/meta"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (in *Tenant) ConvertFrom(raw conversion.Hub) error {
|
func (in *Tenant) ConvertFrom(raw conversion.Hub) error {
|
||||||
@@ -26,28 +27,32 @@ func (in *Tenant) ConvertFrom(raw conversion.Hub) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
in.ObjectMeta = src.ObjectMeta
|
in.ObjectMeta = src.ObjectMeta
|
||||||
in.Spec.Owners = make(OwnerListSpec, 0, len(src.Spec.Owners))
|
in.Spec.Owners = make(api.OwnerListSpec, 0, len(src.Spec.Owners))
|
||||||
|
|
||||||
for index, owner := range src.Spec.Owners {
|
for index, owner := range src.Spec.Owners {
|
||||||
proxySettings := make([]ProxySettings, 0, len(owner.ProxyOperations))
|
proxySettings := make([]api.ProxySettings, 0, len(owner.ProxyOperations))
|
||||||
|
|
||||||
for _, proxyOp := range owner.ProxyOperations {
|
for _, proxyOp := range owner.ProxyOperations {
|
||||||
ops := make([]ProxyOperation, 0, len(proxyOp.Operations))
|
ops := make([]api.ProxyOperation, 0, len(proxyOp.Operations))
|
||||||
|
|
||||||
for _, op := range proxyOp.Operations {
|
for _, op := range proxyOp.Operations {
|
||||||
ops = append(ops, ProxyOperation(op))
|
ops = append(ops, api.ProxyOperation(op))
|
||||||
}
|
}
|
||||||
|
|
||||||
proxySettings = append(proxySettings, ProxySettings{
|
proxySettings = append(proxySettings, api.ProxySettings{
|
||||||
Kind: ProxyServiceKind(proxyOp.Kind),
|
Kind: api.ProxyServiceKind(proxyOp.Kind),
|
||||||
Operations: ops,
|
Operations: ops,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
in.Spec.Owners = append(in.Spec.Owners, OwnerSpec{
|
in.Spec.Owners = append(in.Spec.Owners, api.OwnerSpec{
|
||||||
Kind: OwnerKind(owner.Kind),
|
CoreOwnerSpec: api.CoreOwnerSpec{
|
||||||
|
UserSpec: api.UserSpec{
|
||||||
|
Kind: api.OwnerKind(owner.Kind),
|
||||||
Name: owner.Name,
|
Name: owner.Name,
|
||||||
|
},
|
||||||
ClusterRoles: owner.GetRoles(*src, index),
|
ClusterRoles: owner.GetRoles(*src, index),
|
||||||
|
},
|
||||||
ProxyOperations: proxySettings,
|
ProxyOperations: proxySettings,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -59,28 +64,28 @@ func (in *Tenant) ConvertFrom(raw conversion.Hub) error {
|
|||||||
|
|
||||||
in.Spec.NamespaceOptions.AdditionalMetadata = nsOpts.AdditionalMetadata
|
in.Spec.NamespaceOptions.AdditionalMetadata = nsOpts.AdditionalMetadata
|
||||||
|
|
||||||
if value, found := annotations[api.ForbiddenNamespaceLabelsAnnotation]; found {
|
if value, found := annotations[meta.ForbiddenNamespaceLabelsAnnotation]; found {
|
||||||
in.Spec.NamespaceOptions.ForbiddenLabels.Exact = strings.Split(value, ",")
|
in.Spec.NamespaceOptions.ForbiddenLabels.Exact = strings.Split(value, ",")
|
||||||
|
|
||||||
delete(annotations, api.ForbiddenNamespaceLabelsAnnotation)
|
delete(annotations, meta.ForbiddenNamespaceLabelsAnnotation)
|
||||||
}
|
}
|
||||||
|
|
||||||
if value, found := annotations[api.ForbiddenNamespaceLabelsRegexpAnnotation]; found {
|
if value, found := annotations[meta.ForbiddenNamespaceLabelsRegexpAnnotation]; found {
|
||||||
in.Spec.NamespaceOptions.ForbiddenLabels.Regex = value
|
in.Spec.NamespaceOptions.ForbiddenLabels.Regex = value
|
||||||
|
|
||||||
delete(annotations, api.ForbiddenNamespaceLabelsRegexpAnnotation)
|
delete(annotations, meta.ForbiddenNamespaceLabelsRegexpAnnotation)
|
||||||
}
|
}
|
||||||
|
|
||||||
if value, found := annotations[api.ForbiddenNamespaceAnnotationsAnnotation]; found {
|
if value, found := annotations[meta.ForbiddenNamespaceAnnotationsAnnotation]; found {
|
||||||
in.Spec.NamespaceOptions.ForbiddenAnnotations.Exact = strings.Split(value, ",")
|
in.Spec.NamespaceOptions.ForbiddenAnnotations.Exact = strings.Split(value, ",")
|
||||||
|
|
||||||
delete(annotations, api.ForbiddenNamespaceAnnotationsAnnotation)
|
delete(annotations, meta.ForbiddenNamespaceAnnotationsAnnotation)
|
||||||
}
|
}
|
||||||
|
|
||||||
if value, found := annotations[api.ForbiddenNamespaceAnnotationsRegexpAnnotation]; found {
|
if value, found := annotations[meta.ForbiddenNamespaceAnnotationsRegexpAnnotation]; found {
|
||||||
in.Spec.NamespaceOptions.ForbiddenAnnotations.Regex = value
|
in.Spec.NamespaceOptions.ForbiddenAnnotations.Regex = value
|
||||||
|
|
||||||
delete(annotations, api.ForbiddenNamespaceAnnotationsRegexpAnnotation)
|
delete(annotations, meta.ForbiddenNamespaceAnnotationsRegexpAnnotation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,10 +149,10 @@ func (in *Tenant) ConvertFrom(raw conversion.Hub) error {
|
|||||||
in.Spec.Cordoned = value
|
in.Spec.Cordoned = value
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, found := annotations[api.ProtectedTenantAnnotation]; found {
|
if _, found := annotations[meta.ProtectedTenantAnnotation]; found {
|
||||||
in.Spec.PreventDeletion = true
|
in.Spec.PreventDeletion = true
|
||||||
|
|
||||||
delete(annotations, api.ProtectedTenantAnnotation)
|
delete(annotations, meta.ProtectedTenantAnnotation)
|
||||||
}
|
}
|
||||||
|
|
||||||
in.SetAnnotations(annotations)
|
in.SetAnnotations(annotations)
|
||||||
@@ -215,19 +220,19 @@ func (in *Tenant) ConvertTo(raw conversion.Hub) error {
|
|||||||
dst.Spec.NamespaceOptions.AdditionalMetadata = nsOpts.AdditionalMetadata
|
dst.Spec.NamespaceOptions.AdditionalMetadata = nsOpts.AdditionalMetadata
|
||||||
|
|
||||||
if exact := nsOpts.ForbiddenAnnotations.Exact; len(exact) > 0 {
|
if exact := nsOpts.ForbiddenAnnotations.Exact; len(exact) > 0 {
|
||||||
annotations[api.ForbiddenNamespaceAnnotationsAnnotation] = strings.Join(exact, ",")
|
annotations[meta.ForbiddenNamespaceAnnotationsAnnotation] = strings.Join(exact, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
if regex := nsOpts.ForbiddenAnnotations.Regex; len(regex) > 0 {
|
if regex := nsOpts.ForbiddenAnnotations.Regex; len(regex) > 0 {
|
||||||
annotations[api.ForbiddenNamespaceAnnotationsRegexpAnnotation] = regex
|
annotations[meta.ForbiddenNamespaceAnnotationsRegexpAnnotation] = regex
|
||||||
}
|
}
|
||||||
|
|
||||||
if exact := nsOpts.ForbiddenLabels.Exact; len(exact) > 0 {
|
if exact := nsOpts.ForbiddenLabels.Exact; len(exact) > 0 {
|
||||||
annotations[api.ForbiddenNamespaceLabelsAnnotation] = strings.Join(exact, ",")
|
annotations[meta.ForbiddenNamespaceLabelsAnnotation] = strings.Join(exact, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
if regex := nsOpts.ForbiddenLabels.Regex; len(regex) > 0 {
|
if regex := nsOpts.ForbiddenLabels.Regex; len(regex) > 0 {
|
||||||
annotations[api.ForbiddenNamespaceLabelsRegexpAnnotation] = regex
|
annotations[meta.ForbiddenNamespaceLabelsRegexpAnnotation] = regex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,7 +269,7 @@ func (in *Tenant) ConvertTo(raw conversion.Hub) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if in.Spec.PreventDeletion {
|
if in.Spec.PreventDeletion {
|
||||||
annotations[api.ProtectedTenantAnnotation] = "true" //nolint:goconst
|
annotations[meta.ProtectedTenantAnnotation] = "true" //nolint:goconst
|
||||||
}
|
}
|
||||||
|
|
||||||
if in.Spec.Cordoned {
|
if in.Spec.Cordoned {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta2
|
package v1beta2
|
||||||
@@ -13,6 +13,18 @@ import (
|
|||||||
"github.com/projectcapsule/capsule/pkg/api"
|
"github.com/projectcapsule/capsule/pkg/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (in *Tenant) GetRoleBindings() []api.AdditionalRoleBindingsSpec {
|
||||||
|
roleBindings := make([]api.AdditionalRoleBindingsSpec, 0, len(in.Spec.AdditionalRoleBindings))
|
||||||
|
|
||||||
|
for _, owner := range in.Status.Owners {
|
||||||
|
roleBindings = append(roleBindings, owner.ToAdditionalRolebindings()...)
|
||||||
|
}
|
||||||
|
|
||||||
|
roleBindings = append(roleBindings, in.Spec.AdditionalRoleBindings...)
|
||||||
|
|
||||||
|
return roleBindings
|
||||||
|
}
|
||||||
|
|
||||||
func (in *Tenant) IsFull() bool {
|
func (in *Tenant) IsFull() bool {
|
||||||
// we don't have limits on assigned Namespaces
|
// we don't have limits on assigned Namespaces
|
||||||
if in.Spec.NamespaceOptions == nil || in.Spec.NamespaceOptions.Quota == nil {
|
if in.Spec.NamespaceOptions == nil || in.Spec.NamespaceOptions.Quota == nil {
|
||||||
@@ -37,14 +49,14 @@ func (in *Tenant) AssignNamespaces(namespaces []corev1.Namespace) {
|
|||||||
in.Status.Size = uint(len(l))
|
in.Status.Size = uint(len(l))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in *Tenant) GetOwnerProxySettings(name string, kind OwnerKind) []ProxySettings {
|
func (in *Tenant) GetOwnerProxySettings(name string, kind api.OwnerKind) []api.ProxySettings {
|
||||||
return in.Spec.Owners.FindOwner(name, kind).ProxyOperations
|
return in.Spec.Owners.FindOwner(name, kind).ProxyOperations
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetClusterRolePermissions returns a map where the clusterRole is the key
|
// GetClusterRolePermissions returns a map where the clusterRole is the key
|
||||||
// and the value is a list of permission subjects (kind and name) that reference that role.
|
// and the value is a list of permission subjects (kind and name) that reference that role.
|
||||||
// These mappings are gathered from the owners and additionalRolebindings spec.
|
// These mappings are gathered from the owners and additionalRolebindings spec.
|
||||||
func (in *Tenant) GetSubjectsByClusterRoles(ignoreOwnerKind []OwnerKind) (rolePerms map[string][]rbacv1.Subject) {
|
func (in *Tenant) GetSubjectsByClusterRoles(ignoreOwnerKind []api.OwnerKind) (rolePerms map[string][]rbacv1.Subject) {
|
||||||
rolePerms = make(map[string][]rbacv1.Subject)
|
rolePerms = make(map[string][]rbacv1.Subject)
|
||||||
|
|
||||||
// Helper to add permissions for a given clusterRole
|
// Helper to add permissions for a given clusterRole
|
||||||
@@ -93,11 +105,11 @@ func (in *Tenant) GetSubjectsByClusterRoles(ignoreOwnerKind []OwnerKind) (rolePe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return rolePerms
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the permissions for a tenant ordered by groups and users.
|
// Get the permissions for a tenant ordered by groups and users.
|
||||||
func (in *Tenant) GetClusterRolesBySubject(ignoreOwnerKind []OwnerKind) (maps map[string]map[string]api.TenantSubjectRoles) {
|
func (in *Tenant) GetClusterRolesBySubject(ignoreOwnerKind []api.OwnerKind) (maps map[string]map[string]api.TenantSubjectRoles) {
|
||||||
maps = make(map[string]map[string]api.TenantSubjectRoles)
|
maps = make(map[string]map[string]api.TenantSubjectRoles)
|
||||||
|
|
||||||
// Initialize a nested map for kind ("User", "Group") and name
|
// Initialize a nested map for kind ("User", "Group") and name
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta2
|
package v1beta2
|
||||||
@@ -13,23 +13,35 @@ import (
|
|||||||
|
|
||||||
var tenant = &Tenant{
|
var tenant = &Tenant{
|
||||||
Spec: TenantSpec{
|
Spec: TenantSpec{
|
||||||
Owners: []OwnerSpec{
|
Owners: []api.OwnerSpec{
|
||||||
{
|
{
|
||||||
|
CoreOwnerSpec: api.CoreOwnerSpec{
|
||||||
|
UserSpec: api.UserSpec{
|
||||||
Kind: "User",
|
Kind: "User",
|
||||||
Name: "user1",
|
Name: "user1",
|
||||||
|
},
|
||||||
ClusterRoles: []string{"cluster-admin", "read-only"},
|
ClusterRoles: []string{"cluster-admin", "read-only"},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Kind: "Group",
|
|
||||||
Name: "group1",
|
|
||||||
ClusterRoles: []string{"edit"},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Kind: ServiceAccountOwner,
|
CoreOwnerSpec: api.CoreOwnerSpec{
|
||||||
|
UserSpec: api.UserSpec{
|
||||||
|
Kind: "Group",
|
||||||
|
Name: "group1",
|
||||||
|
},
|
||||||
|
ClusterRoles: []string{"edit"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CoreOwnerSpec: api.CoreOwnerSpec{
|
||||||
|
UserSpec: api.UserSpec{
|
||||||
|
Kind: api.ServiceAccountOwner,
|
||||||
Name: "service",
|
Name: "service",
|
||||||
|
},
|
||||||
ClusterRoles: []string{"read-only"},
|
ClusterRoles: []string{"read-only"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
AdditionalRoleBindings: []api.AdditionalRoleBindingsSpec{
|
AdditionalRoleBindings: []api.AdditionalRoleBindingsSpec{
|
||||||
{
|
{
|
||||||
ClusterRoleName: "developer",
|
ClusterRoleName: "developer",
|
||||||
@@ -96,7 +108,7 @@ func TestGetSubjectsByClusterRoles(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ignore SubjectTypes (Ignores ServiceAccounts)
|
// Ignore SubjectTypes (Ignores ServiceAccounts)
|
||||||
ignored := tenant.GetSubjectsByClusterRoles([]OwnerKind{"ServiceAccount"})
|
ignored := tenant.GetSubjectsByClusterRoles([]api.OwnerKind{"ServiceAccount"})
|
||||||
expectedIgnored := map[string][]rbacv1.Subject{
|
expectedIgnored := map[string][]rbacv1.Subject{
|
||||||
"cluster-admin": {
|
"cluster-admin": {
|
||||||
{Kind: "User", Name: "user1"},
|
{Kind: "User", Name: "user1"},
|
||||||
@@ -156,7 +168,7 @@ func TestGetClusterRolesBySubject(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
delete(expected, "ServiceAccount")
|
delete(expected, "ServiceAccount")
|
||||||
ignored := tenant.GetClusterRolesBySubject([]OwnerKind{"ServiceAccount"})
|
ignored := tenant.GetClusterRolesBySubject([]api.OwnerKind{"ServiceAccount"})
|
||||||
|
|
||||||
if !reflect.DeepEqual(ignored, expected) {
|
if !reflect.DeepEqual(ignored, expected) {
|
||||||
t.Errorf("Expected %v, but got %v", expected, ignored)
|
t.Errorf("Expected %v, but got %v", expected, ignored)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta2
|
package v1beta2
|
||||||
@@ -28,5 +28,5 @@ func GetTypeLabel(t metav1.Object) (label string, err error) {
|
|||||||
err = fmt.Errorf("type %T is not mapped as Capsule label recognized", v)
|
err = fmt.Errorf("type %T is not mapped as Capsule label recognized", v)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return label, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta2
|
package v1beta2
|
||||||
|
|
||||||
|
import (
|
||||||
|
k8stypes "k8s.io/apimachinery/pkg/types"
|
||||||
|
|
||||||
|
"github.com/projectcapsule/capsule/pkg/api"
|
||||||
|
"github.com/projectcapsule/capsule/pkg/api/meta"
|
||||||
|
)
|
||||||
|
|
||||||
// +kubebuilder:validation:Enum=Cordoned;Active
|
// +kubebuilder:validation:Enum=Cordoned;Active
|
||||||
type tenantState string
|
type tenantState string
|
||||||
|
|
||||||
@@ -13,11 +20,105 @@ const (
|
|||||||
|
|
||||||
// Returns the observed state of the Tenant.
|
// Returns the observed state of the Tenant.
|
||||||
type TenantStatus struct {
|
type TenantStatus struct {
|
||||||
|
// Allowed Cluster Objects within Tenant
|
||||||
|
TenantAvailableStatus `json:",inline"`
|
||||||
|
|
||||||
|
// Collected owners for this tenant
|
||||||
|
Owners api.OwnerStatusListSpec `json:"owners,omitempty"`
|
||||||
// +kubebuilder:default=Active
|
// +kubebuilder:default=Active
|
||||||
// The operational state of the Tenant. Possible values are "Active", "Cordoned".
|
// The operational state of the Tenant. Possible values are "Active", "Cordoned".
|
||||||
State tenantState `json:"state"`
|
State tenantState `json:"state"`
|
||||||
// How many namespaces are assigned to the Tenant.
|
// How many namespaces are assigned to the Tenant.
|
||||||
Size uint `json:"size"`
|
Size uint `json:"size"`
|
||||||
// List of namespaces assigned to the Tenant.
|
// List of namespaces assigned to the Tenant. (Deprecated)
|
||||||
Namespaces []string `json:"namespaces,omitempty"`
|
Namespaces []string `json:"namespaces,omitempty"`
|
||||||
|
// Tracks state for the namespaces associated with this tenant
|
||||||
|
Spaces []*TenantStatusNamespaceItem `json:"spaces,omitempty"`
|
||||||
|
// Tenant Condition
|
||||||
|
Conditions meta.ConditionList `json:"conditions"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TenantStatusNamespaceItem struct {
|
||||||
|
// Conditions
|
||||||
|
Conditions meta.ConditionList `json:"conditions"`
|
||||||
|
// Namespace Name
|
||||||
|
Name string `json:"name"`
|
||||||
|
// Namespace UID
|
||||||
|
UID k8stypes.UID `json:"uid,omitempty"`
|
||||||
|
// Managed Metadata
|
||||||
|
Metadata *TenantStatusNamespaceMetadata `json:"metadata,omitempty"`
|
||||||
|
// Managed Metadata
|
||||||
|
//+optional
|
||||||
|
Enforce TenantStatusNamespaceEnforcement `json:"enforce,omitzero"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TenantStatusNamespaceEnforcement struct {
|
||||||
|
// Registries which are allowed within this namespace
|
||||||
|
Registries []api.OCIRegistry `json:"registry,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TenantStatusNamespaceMetadata struct {
|
||||||
|
// Managed Labels
|
||||||
|
Labels map[string]string `json:"labels,omitempty"`
|
||||||
|
// Managed Annotations
|
||||||
|
Annotations map[string]string `json:"annotations,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TenantAvailableStatus struct {
|
||||||
|
// Available Class Types within Tenant
|
||||||
|
// +optional
|
||||||
|
Classes TenantAvailableClassesStatus `json:"classes,omitzero"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TenantAvailableClassesStatus struct {
|
||||||
|
// Available Storageclasses (Only collected if any matching condition is specified)
|
||||||
|
StorageClasses []string `json:"storage,omitempty"`
|
||||||
|
// Available PriorityClasses
|
||||||
|
PriorityClasses []string `json:"priority,omitempty"`
|
||||||
|
// Available StorageClasses
|
||||||
|
RuntimeClasses []string `json:"runtime,omitempty"`
|
||||||
|
// Available GatewayClasses
|
||||||
|
GatewayClasses []string `json:"gateway,omitempty"`
|
||||||
|
// Available DeviceClasses
|
||||||
|
DeviceClasses []string `json:"device,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ms *TenantStatus) GetInstance(stat *TenantStatusNamespaceItem) *TenantStatusNamespaceItem {
|
||||||
|
for _, source := range ms.Spaces {
|
||||||
|
if ms.instancequal(source, stat) {
|
||||||
|
return source
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ms *TenantStatus) UpdateInstance(stat *TenantStatusNamespaceItem) {
|
||||||
|
// Check if the tenant is already present in the status
|
||||||
|
for i, source := range ms.Spaces {
|
||||||
|
if ms.instancequal(source, stat) {
|
||||||
|
ms.Spaces[i] = stat
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ms.Spaces = append(ms.Spaces, stat)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ms *TenantStatus) RemoveInstance(stat *TenantStatusNamespaceItem) {
|
||||||
|
// Filter out the datasource with given UID
|
||||||
|
filter := []*TenantStatusNamespaceItem{}
|
||||||
|
|
||||||
|
for _, source := range ms.Spaces {
|
||||||
|
if !ms.instancequal(source, stat) {
|
||||||
|
filter = append(filter, source)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ms.Spaces = filter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ms *TenantStatus) instancequal(a, b *TenantStatusNamespaceItem) bool {
|
||||||
|
return a.Name == b.Name
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,35 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta2
|
package v1beta2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
|
||||||
"github.com/projectcapsule/capsule/pkg/api"
|
"github.com/projectcapsule/capsule/pkg/api"
|
||||||
|
"github.com/projectcapsule/capsule/pkg/api/meta"
|
||||||
|
"github.com/projectcapsule/capsule/pkg/runtime/selectors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TenantSpec defines the desired state of Tenant.
|
// TenantSpec defines the desired state of Tenant.
|
||||||
type TenantSpec struct {
|
type TenantSpec struct {
|
||||||
// Specifies the owners of the Tenant. Mandatory.
|
// Specify Permissions for the Tenant.
|
||||||
Owners OwnerListSpec `json:"owners"`
|
// +optional
|
||||||
|
Permissions Permissions `json:"permissions,omitzero"`
|
||||||
|
// Specify enforcement specifications for the scope of the Tenant.
|
||||||
|
// We are moving all configuration enforcement. per namespace into a rule construct.
|
||||||
|
// It's currently not final.
|
||||||
|
//
|
||||||
|
// Read More: https://projectcapsule.dev/docs/tenants/rules/
|
||||||
|
//+optional
|
||||||
|
Rules []*NamespaceRule `json:"rules,omitzero"`
|
||||||
|
|
||||||
|
// Specifies the owners of the Tenant.
|
||||||
|
// Optional
|
||||||
|
Owners api.OwnerListSpec `json:"owners,omitempty"`
|
||||||
// Specifies options for the Namespaces, such as additional metadata or maximum number of namespaces allowed for that Tenant. Once the namespace quota assigned to the Tenant has been reached, the Tenant owner cannot create further namespaces. Optional.
|
// Specifies options for the Namespaces, such as additional metadata or maximum number of namespaces allowed for that Tenant. Once the namespace quota assigned to the Tenant has been reached, the Tenant owner cannot create further namespaces. Optional.
|
||||||
NamespaceOptions *NamespaceOptions `json:"namespaceOptions,omitempty"`
|
NamespaceOptions *NamespaceOptions `json:"namespaceOptions,omitempty"`
|
||||||
// Specifies options for the Service, such as additional metadata or block of certain type of Services. Optional.
|
// Specifies options for the Service, such as additional metadata or block of certain type of Services. Optional.
|
||||||
@@ -25,21 +42,15 @@ type TenantSpec struct {
|
|||||||
// Optional.
|
// Optional.
|
||||||
StorageClasses *api.DefaultAllowedListSpec `json:"storageClasses,omitempty"`
|
StorageClasses *api.DefaultAllowedListSpec `json:"storageClasses,omitempty"`
|
||||||
// Specifies options for the Ingress resources, such as allowed hostnames and IngressClass. Optional.
|
// Specifies options for the Ingress resources, such as allowed hostnames and IngressClass. Optional.
|
||||||
IngressOptions IngressOptions `json:"ingressOptions,omitempty"`
|
// +optional
|
||||||
// Specifies the trusted Image Registries assigned to the Tenant. Capsule assures that all Pods resources created in the Tenant can use only one of the allowed trusted registries. Optional.
|
IngressOptions IngressOptions `json:"ingressOptions,omitzero"`
|
||||||
ContainerRegistries *api.AllowedListSpec `json:"containerRegistries,omitempty"`
|
|
||||||
// Specifies the label to control the placement of pods on a given pool of worker nodes. All namespaces created within the Tenant will have the node selector annotation. This annotation tells the Kubernetes scheduler to place pods on the nodes having the selector label. Optional.
|
// Specifies the label to control the placement of pods on a given pool of worker nodes. All namespaces created within the Tenant will have the node selector annotation. This annotation tells the Kubernetes scheduler to place pods on the nodes having the selector label. Optional.
|
||||||
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
|
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
|
||||||
// Specifies the NetworkPolicies assigned to the Tenant. The assigned NetworkPolicies are inherited by any namespace created in the Tenant. Optional.
|
|
||||||
NetworkPolicies api.NetworkPolicySpec `json:"networkPolicies,omitempty"`
|
|
||||||
// Specifies the resource min/max usage restrictions to the Tenant. The assigned values are inherited by any namespace created in the Tenant. Optional.
|
|
||||||
LimitRanges api.LimitRangesSpec `json:"limitRanges,omitempty"`
|
|
||||||
// Specifies a list of ResourceQuota resources assigned to the Tenant. The assigned values are inherited by any namespace created in the Tenant. The Capsule operator aggregates ResourceQuota at Tenant level, so that the hard quota is never crossed for the given Tenant. This permits the Tenant owner to consume resources in the Tenant regardless of the namespace. Optional.
|
// Specifies a list of ResourceQuota resources assigned to the Tenant. The assigned values are inherited by any namespace created in the Tenant. The Capsule operator aggregates ResourceQuota at Tenant level, so that the hard quota is never crossed for the given Tenant. This permits the Tenant owner to consume resources in the Tenant regardless of the namespace. Optional.
|
||||||
ResourceQuota api.ResourceQuotaSpec `json:"resourceQuotas,omitempty"`
|
// +optional
|
||||||
|
ResourceQuota api.ResourceQuotaSpec `json:"resourceQuotas,omitzero"`
|
||||||
// Specifies additional RoleBindings assigned to the Tenant. Capsule will ensure that all namespaces in the Tenant always contain the RoleBinding for the given ClusterRole. Optional.
|
// Specifies additional RoleBindings assigned to the Tenant. Capsule will ensure that all namespaces in the Tenant always contain the RoleBinding for the given ClusterRole. Optional.
|
||||||
AdditionalRoleBindings []api.AdditionalRoleBindingsSpec `json:"additionalRoleBindings,omitempty"`
|
AdditionalRoleBindings []api.AdditionalRoleBindingsSpec `json:"additionalRoleBindings,omitempty"`
|
||||||
// Specify the allowed values for the imagePullPolicies option in Pod resources. Capsule assures that all Pod resources created in the Tenant can use only one of the allowed policy. Optional.
|
|
||||||
ImagePullPolicies []api.ImagePullPolicySpec `json:"imagePullPolicies,omitempty"`
|
|
||||||
// Specifies the allowed RuntimeClasses assigned to the Tenant.
|
// Specifies the allowed RuntimeClasses assigned to the Tenant.
|
||||||
// Capsule assures that all Pods resources created in the Tenant can use only one of the allowed RuntimeClasses.
|
// Capsule assures that all Pods resources created in the Tenant can use only one of the allowed RuntimeClasses.
|
||||||
// Optional.
|
// Optional.
|
||||||
@@ -49,6 +60,11 @@ type TenantSpec struct {
|
|||||||
// A default value can be specified, and all the Pod resources created will inherit the declared class.
|
// A default value can be specified, and all the Pod resources created will inherit the declared class.
|
||||||
// Optional.
|
// Optional.
|
||||||
PriorityClasses *api.DefaultAllowedListSpec `json:"priorityClasses,omitempty"`
|
PriorityClasses *api.DefaultAllowedListSpec `json:"priorityClasses,omitempty"`
|
||||||
|
// Specifies options for the DeviceClass resources.
|
||||||
|
DeviceClasses *api.SelectorAllowedListSpec `json:"deviceClasses,omitempty"`
|
||||||
|
// Specifies options for the GatewayClass resources.
|
||||||
|
// +optional
|
||||||
|
GatewayOptions GatewayOptions `json:"gatewayOptions,omitzero"`
|
||||||
// Toggling the Tenant resources cordoning, when enable resources cannot be deleted.
|
// Toggling the Tenant resources cordoning, when enable resources cannot be deleted.
|
||||||
//+kubebuilder:default:=false
|
//+kubebuilder:default:=false
|
||||||
Cordoned bool `json:"cordoned,omitempty"`
|
Cordoned bool `json:"cordoned,omitempty"`
|
||||||
@@ -65,33 +81,77 @@ type TenantSpec struct {
|
|||||||
// If unset, Tenant uses CapsuleConfiguration's forceTenantPrefix
|
// If unset, Tenant uses CapsuleConfiguration's forceTenantPrefix
|
||||||
// Optional
|
// Optional
|
||||||
ForceTenantPrefix *bool `json:"forceTenantPrefix,omitempty"`
|
ForceTenantPrefix *bool `json:"forceTenantPrefix,omitempty"`
|
||||||
|
|
||||||
|
// Deprecated: Use Enforcement.Registries instead
|
||||||
|
//
|
||||||
|
// Specifies the trusted Image Registries assigned to the Tenant. Capsule assures that all Pods resources created in the Tenant can use only one of the allowed trusted registries. Optional.
|
||||||
|
ContainerRegistries *api.AllowedListSpec `json:"containerRegistries,omitempty"`
|
||||||
|
// Deprecated: Use Enforcement.Registries instead
|
||||||
|
//
|
||||||
|
// Specify the allowed values for the imagePullPolicies option in Pod resources. Capsule assures that all Pod resources created in the Tenant can use only one of the allowed policy. Optional.
|
||||||
|
ImagePullPolicies []api.ImagePullPolicySpec `json:"imagePullPolicies,omitempty"`
|
||||||
|
|
||||||
|
// Deprecated: Use Tenant Replications instead (https://projectcapsule.dev/docs/replications/)
|
||||||
|
//
|
||||||
|
// Specifies the NetworkPolicies assigned to the Tenant. The assigned NetworkPolicies are inherited by any namespace created in the Tenant. Optional.
|
||||||
|
// +optional
|
||||||
|
NetworkPolicies api.NetworkPolicySpec `json:"networkPolicies,omitzero"`
|
||||||
|
// Deprecated: Use Tenant Replications instead (https://projectcapsule.dev/docs/replications/)
|
||||||
|
//
|
||||||
|
// Specifies the resource min/max usage restrictions to the Tenant. The assigned values are inherited by any namespace created in the Tenant. Optional.
|
||||||
|
// +optional
|
||||||
|
LimitRanges api.LimitRangesSpec `json:"limitRanges,omitzero"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Permissions struct {
|
||||||
|
// Matches TenantOwner objects which are promoted to owners of this tenant
|
||||||
|
// The elements are OR operations and independent. You can see the resulting Tenant Owners
|
||||||
|
// in the Status.Owners specification of the Tenant.
|
||||||
|
MatchOwners []*metav1.LabelSelector `json:"matchOwners,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Permissions) ListMatchingOwners(
|
||||||
|
ctx context.Context,
|
||||||
|
c client.Client,
|
||||||
|
tnt string,
|
||||||
|
opts ...client.ListOption,
|
||||||
|
) ([]*TenantOwner, error) {
|
||||||
|
defaultSelector := &metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{
|
||||||
|
meta.NewTenantLabel: tnt,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return selectors.ListBySelectors[*TenantOwner](ctx, c, &TenantOwnerList{}, append(p.MatchOwners, defaultSelector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// +kubebuilder:object:root=true
|
// +kubebuilder:object:root=true
|
||||||
// +kubebuilder:storageversion
|
// +kubebuilder:storageversion
|
||||||
// +kubebuilder:subresource:status
|
// +kubebuilder:subresource:status
|
||||||
// +kubebuilder:resource:scope=Cluster,shortName=tnt
|
// +kubebuilder:resource:scope=Cluster,shortName=tnt
|
||||||
// +kubebuilder:printcolumn:name="State",type="string",JSONPath=".status.state",description="The actual state of the Tenant"
|
// +kubebuilder:printcolumn:name="State",type="string",JSONPath=".status.conditions[?(@.type==\"Cordoned\")].reason",description="The actual state of the Tenant"
|
||||||
// +kubebuilder:printcolumn:name="Namespace quota",type="integer",JSONPath=".spec.namespaceOptions.quota",description="The max amount of Namespaces can be created"
|
// +kubebuilder:printcolumn:name="Namespace quota",type="integer",JSONPath=".spec.namespaceOptions.quota",description="The max amount of Namespaces can be created"
|
||||||
// +kubebuilder:printcolumn:name="Namespace count",type="integer",JSONPath=".status.size",description="The total amount of Namespaces in use"
|
// +kubebuilder:printcolumn:name="Namespace count",type="integer",JSONPath=".status.size",description="The total amount of Namespaces in use"
|
||||||
// +kubebuilder:printcolumn:name="Node selector",type="string",JSONPath=".spec.nodeSelector",description="Node Selector applied to Pods"
|
// +kubebuilder:printcolumn:name="Node selector",type="string",JSONPath=".spec.nodeSelector",description="Node Selector applied to Pods"
|
||||||
|
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description="Reconcile Status for the tenant"
|
||||||
|
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description="Reconcile Message for the tenant"
|
||||||
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Age"
|
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Age"
|
||||||
|
|
||||||
// Tenant is the Schema for the tenants API.
|
// Tenant is the Schema for the tenants API.
|
||||||
type Tenant struct {
|
type Tenant struct {
|
||||||
metav1.TypeMeta `json:",inline"`
|
metav1.TypeMeta `json:",inline"`
|
||||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
|
||||||
|
|
||||||
Spec TenantSpec `json:"spec,omitempty"`
|
// +optional
|
||||||
Status TenantStatus `json:"status,omitempty"`
|
metav1.ObjectMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
Spec TenantSpec `json:"spec,omitzero"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
Status TenantStatus `json:"status,omitzero"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in *Tenant) GetNamespaces() (res []string) {
|
func (in *Tenant) GetNamespaces() (res []string) {
|
||||||
res = make([]string, 0, len(in.Status.Namespaces))
|
return in.Status.Namespaces
|
||||||
|
|
||||||
res = append(res, in.Status.Namespaces...)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// +kubebuilder:object:root=true
|
// +kubebuilder:object:root=true
|
||||||
@@ -99,7 +159,8 @@ func (in *Tenant) GetNamespaces() (res []string) {
|
|||||||
// TenantList contains a list of Tenant.
|
// TenantList contains a list of Tenant.
|
||||||
type TenantList struct {
|
type TenantList struct {
|
||||||
metav1.TypeMeta `json:",inline"`
|
metav1.TypeMeta `json:",inline"`
|
||||||
metav1.ListMeta `json:"metadata,omitempty"`
|
metav1.ListMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
Items []Tenant `json:"items"`
|
Items []Tenant `json:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
60
api/v1beta2/tenantowner_types.go
Normal file
60
api/v1beta2/tenantowner_types.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package v1beta2
|
||||||
|
|
||||||
|
import (
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
"github.com/projectcapsule/capsule/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TenantOwnerSpec defines the desired state of TenantOwner.
|
||||||
|
type TenantOwnerSpec struct {
|
||||||
|
// Subject
|
||||||
|
api.CoreOwnerSpec `json:",inline"`
|
||||||
|
|
||||||
|
// Adds the given subject as capsule user. When enabled this subject does not have to be
|
||||||
|
// mentioned in the CapsuleConfiguration as Capsule User. In almost all scenarios Tenant Owners
|
||||||
|
// must be Capsule Users.
|
||||||
|
//+kubebuilder:default:=true
|
||||||
|
Aggregate bool `json:"aggregate"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TenantOwnerStatus defines the observed state of TenantOwner.
|
||||||
|
type TenantOwnerStatus struct{}
|
||||||
|
|
||||||
|
// +kubebuilder:object:root=true
|
||||||
|
// +kubebuilder:subresource:status
|
||||||
|
// +kubebuilder:resource:scope=Cluster
|
||||||
|
|
||||||
|
// TenantOwner is the Schema for the tenantowners API.
|
||||||
|
type TenantOwner struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
|
||||||
|
// metadata is a standard object metadata.
|
||||||
|
// +optional
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
|
// spec defines the desired state of TenantOwner.
|
||||||
|
// +required
|
||||||
|
Spec TenantOwnerSpec `json:"spec"`
|
||||||
|
|
||||||
|
// status defines the observed state of TenantOwner.
|
||||||
|
// +optional
|
||||||
|
Status TenantOwnerStatus `json:"status,omitzero"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:object:root=true
|
||||||
|
|
||||||
|
// TenantOwnerList contains a list of TenantOwner.
|
||||||
|
type TenantOwnerList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ListMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
|
Items []TenantOwner `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SchemeBuilder.Register(&TenantOwner{}, &TenantOwnerList{})
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta2
|
package v1beta2
|
||||||
@@ -10,9 +10,11 @@ import (
|
|||||||
|
|
||||||
// GlobalTenantResourceSpec defines the desired state of GlobalTenantResource.
|
// GlobalTenantResourceSpec defines the desired state of GlobalTenantResource.
|
||||||
type GlobalTenantResourceSpec struct {
|
type GlobalTenantResourceSpec struct {
|
||||||
// Defines the Tenant selector used target the tenants on which resources must be propagated.
|
|
||||||
TenantSelector metav1.LabelSelector `json:"tenantSelector,omitempty"`
|
|
||||||
TenantResourceSpec `json:",inline"`
|
TenantResourceSpec `json:",inline"`
|
||||||
|
|
||||||
|
// Defines the Tenant selector used target the tenants on which resources must be propagated.
|
||||||
|
// +optional
|
||||||
|
TenantSelector metav1.LabelSelector `json:"tenantSelector,omitzero"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GlobalTenantResourceStatus defines the observed state of GlobalTenantResource.
|
// GlobalTenantResourceStatus defines the observed state of GlobalTenantResource.
|
||||||
@@ -20,7 +22,7 @@ type GlobalTenantResourceStatus struct {
|
|||||||
// List of Tenants addressed by the GlobalTenantResource.
|
// List of Tenants addressed by the GlobalTenantResource.
|
||||||
SelectedTenants []string `json:"selectedTenants"`
|
SelectedTenants []string `json:"selectedTenants"`
|
||||||
// List of the replicated resources for the given TenantResource.
|
// List of the replicated resources for the given TenantResource.
|
||||||
ProcessedItems ProcessedItems `json:"processedItems"`
|
ProcessedItems ProcessedItems `json:"processedItems,omitzero"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProcessedItems []ObjectReferenceStatus
|
type ProcessedItems []ObjectReferenceStatus
|
||||||
@@ -42,10 +44,14 @@ func (p *ProcessedItems) AsSet() sets.Set[string] {
|
|||||||
// GlobalTenantResource allows to propagate resource replications to a specific subset of Tenant resources.
|
// GlobalTenantResource allows to propagate resource replications to a specific subset of Tenant resources.
|
||||||
type GlobalTenantResource struct {
|
type GlobalTenantResource struct {
|
||||||
metav1.TypeMeta `json:",inline"`
|
metav1.TypeMeta `json:",inline"`
|
||||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
|
||||||
|
|
||||||
Spec GlobalTenantResourceSpec `json:"spec,omitempty"`
|
// +optional
|
||||||
Status GlobalTenantResourceStatus `json:"status,omitempty"`
|
metav1.ObjectMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
|
Spec GlobalTenantResourceSpec `json:"spec"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
Status GlobalTenantResourceStatus `json:"status,omitzero"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +kubebuilder:object:root=true
|
// +kubebuilder:object:root=true
|
||||||
@@ -53,7 +59,8 @@ type GlobalTenantResource struct {
|
|||||||
// GlobalTenantResourceList contains a list of GlobalTenantResource.
|
// GlobalTenantResourceList contains a list of GlobalTenantResource.
|
||||||
type GlobalTenantResourceList struct {
|
type GlobalTenantResourceList struct {
|
||||||
metav1.TypeMeta `json:",inline"`
|
metav1.TypeMeta `json:",inline"`
|
||||||
metav1.ListMeta `json:"metadata,omitempty"`
|
metav1.ListMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
Items []GlobalTenantResource `json:"items"`
|
Items []GlobalTenantResource `json:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta2
|
package v1beta2
|
||||||
@@ -57,10 +57,14 @@ type TenantResourceStatus struct {
|
|||||||
// For such cases, the GlobalTenantResource must be used.
|
// For such cases, the GlobalTenantResource must be used.
|
||||||
type TenantResource struct {
|
type TenantResource struct {
|
||||||
metav1.TypeMeta `json:",inline"`
|
metav1.TypeMeta `json:",inline"`
|
||||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
|
||||||
|
|
||||||
Spec TenantResourceSpec `json:"spec,omitempty"`
|
// +optional
|
||||||
Status TenantResourceStatus `json:"status,omitempty"`
|
metav1.ObjectMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
|
Spec TenantResourceSpec `json:"spec"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
Status TenantResourceStatus `json:"status,omitzero"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +kubebuilder:object:root=true
|
// +kubebuilder:object:root=true
|
||||||
@@ -68,7 +72,8 @@ type TenantResource struct {
|
|||||||
// TenantResourceList contains a list of TenantResource.
|
// TenantResourceList contains a list of TenantResource.
|
||||||
type TenantResourceList struct {
|
type TenantResourceList struct {
|
||||||
metav1.TypeMeta `json:",inline"`
|
metav1.TypeMeta `json:",inline"`
|
||||||
metav1.ListMeta `json:"metadata,omitempty"`
|
metav1.ListMeta `json:"metadata,omitzero"`
|
||||||
|
|
||||||
Items []TenantResource `json:"items"`
|
Items []TenantResource `json:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2023 Project Capsule Authors.
|
// Copyright 2020-2026 Project Capsule Authors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package v1beta2
|
package v1beta2
|
||||||
@@ -23,6 +23,7 @@ type ObjectReferenceAbstract struct {
|
|||||||
|
|
||||||
type ObjectReferenceStatus struct {
|
type ObjectReferenceStatus struct {
|
||||||
ObjectReferenceAbstract `json:",inline"`
|
ObjectReferenceAbstract `json:",inline"`
|
||||||
|
|
||||||
// Name of the referent.
|
// Name of the referent.
|
||||||
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@@ -30,6 +31,7 @@ type ObjectReferenceStatus struct {
|
|||||||
|
|
||||||
type ObjectReference struct {
|
type ObjectReference struct {
|
||||||
ObjectReferenceAbstract `json:",inline"`
|
ObjectReferenceAbstract `json:",inline"`
|
||||||
|
|
||||||
// Label selector used to select the given resources in the given Namespace.
|
// Label selector used to select the given resources in the given Namespace.
|
||||||
Selector metav1.LabelSelector `json:"selector"`
|
Selector metav1.LabelSelector `json:"selector"`
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
BIN
assets/customer_logo/odc-noord-logo.png
Normal file
BIN
assets/customer_logo/odc-noord-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
@@ -1,101 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" id="Livello_1" x="0" y="0" version="1.1" viewBox="36.76 68.993 493.611 493.611">
|
||||||
<!-- Generator: Adobe Illustrator 24.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
<style>.st0{fill:#274872}.st2{fill:#5783ab}.st3{fill:#eaecec}</style>
|
||||||
<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
<path d="M243.53 178.65c-.06-4.5-.37-9.02 0-13.49.1-1.22 2.13-3.09 3.45-3.25 6.99-.88 14.03-1.47 21.07-1.8 2.43-.12 3.48-1.05 4.29-3.12 2-5.14 4.08-10.25 6.32-15.29.86-1.93.56-2.83-1.2-4.09-4.42-3.15-4.97-8.41-1.6-12.08 3.7-4.04 8.88-4.09 12.65-.12 3.5 3.68 3.07 8.88-1.39 12.08-1.93 1.39-2.08 2.44-1.22 4.44 2.19 5.06 3.96 10.31 6.33 15.27.65 1.37 2.73 2.73 4.28 2.89 7.57.77 15.19 1.17 22.79 1.64 2.69.16 4.13 1.28 4.21 4.15.1 3.95.43 7.89.66 11.84-1.51.05-3.03.22-4.53.13-12.54-.76-37.47-2.65-37.47-2.65s-27.36 2.32-38.64 3.45z" class="st0"/>
|
||||||
viewBox="0 0 595.28 841.89" style="enable-background:new 0 0 595.28 841.89;" xml:space="preserve">
|
<path fill="#314a70" d="M73.32 483.91c-5.2-2.69-9.26-6.43-12.18-11.22-2.92-4.78-4.38-10.21-4.38-16.28s1.46-11.5 4.38-16.28c2.92-4.78 6.98-8.52 12.18-11.22 5.2-2.69 11.06-4.04 17.59-4.04 6.45 0 12.09 1.35 16.91 4.04 4.82 2.7 8.33 6.55 10.53 11.56l-13.78 7.4c-3.19-5.62-7.78-8.43-13.78-8.43-4.63 0-8.47 1.52-11.5 4.55-3.04 3.04-4.55 7.17-4.55 12.41s1.52 9.38 4.55 12.41c3.04 3.04 6.87 4.55 11.5 4.55 6.07 0 10.66-2.81 13.78-8.43l13.78 7.52c-2.2 4.86-5.71 8.65-10.53 11.39-4.82 2.73-10.46 4.1-16.91 4.1-6.53.01-12.39-1.34-17.59-4.03zm101.85-52.27c5.08 4.52 7.63 11.33 7.63 20.44v34.96h-16.62v-7.63c-3.34 5.69-9.56 8.54-18.67 8.54-4.71 0-8.79-.8-12.24-2.39-3.46-1.59-6.09-3.79-7.91-6.6-1.82-2.81-2.73-6-2.73-9.56 0-5.69 2.14-10.17 6.43-13.44 4.29-3.26 10.91-4.9 19.87-4.9h14.12c0-3.87-1.18-6.85-3.53-8.94-2.35-2.09-5.88-3.13-10.59-3.13-3.26 0-6.47.51-9.62 1.54-3.15 1.03-5.83 2.41-8.03 4.16l-6.38-12.41c3.34-2.35 7.34-4.17 12.01-5.47 4.67-1.29 9.47-1.94 14.4-1.94 9.49 0 16.77 2.26 21.86 6.77zm-15.14 42.25c2.35-1.4 4.02-3.47 5.01-6.21v-6.26h-12.18c-7.29 0-10.93 2.39-10.93 7.17 0 2.28.89 4.08 2.68 5.41 1.78 1.33 4.23 1.99 7.34 1.99 3.03 0 5.72-.7 8.08-2.1zm90.57-45.09c4.67 2.62 8.33 6.3 10.99 11.04 2.66 4.75 3.99 10.27 3.99 16.57s-1.33 11.82-3.99 16.57-6.32 8.43-10.99 11.04-9.85 3.93-15.54 3.93c-7.82 0-13.97-2.47-18.45-7.4v28.58h-17.76v-83.35h16.97v7.06c4.4-5.31 10.82-7.97 19.24-7.97 5.7 0 10.88 1.31 15.54 3.93zm-7.4 39.96c2.92-3.07 4.38-7.19 4.38-12.35s-1.46-9.28-4.38-12.35c-2.92-3.07-6.66-4.61-11.22-4.61s-8.29 1.54-11.22 4.61c-2.92 3.07-4.38 7.19-4.38 12.35s1.46 9.28 4.38 12.35c2.92 3.07 6.66 4.61 11.22 4.61s8.3-1.53 11.22-4.61zm39.91 17.31c-4.86-1.25-8.73-2.83-11.61-4.73l5.92-12.75c2.73 1.75 6.03 3.17 9.91 4.27 3.87 1.1 7.67 1.65 11.39 1.65 7.51 0 11.27-1.86 11.27-5.58 0-1.75-1.03-3-3.07-3.76-2.05-.76-5.2-1.4-9.45-1.94-5.01-.76-9.15-1.63-12.41-2.62-3.26-.99-6.09-2.73-8.48-5.24s-3.59-6.07-3.59-10.7c0-3.87 1.12-7.3 3.36-10.3 2.24-3 5.5-5.33 9.79-7 4.29-1.67 9.35-2.5 15.2-2.5 4.33 0 8.63.48 12.92 1.42 4.29.95 7.84 2.26 10.65 3.93l-5.92 12.64c-5.39-3.04-11.27-4.55-17.65-4.55-3.8 0-6.64.53-8.54 1.59-1.9 1.06-2.85 2.43-2.85 4.1 0 1.9 1.02 3.23 3.07 3.99 2.05.76 5.31 1.48 9.79 2.16 5.01.84 9.11 1.73 12.3 2.68 3.19.95 5.96 2.68 8.31 5.18 2.35 2.5 3.53 6 3.53 10.48 0 3.8-1.14 7.17-3.42 10.13-2.28 2.96-5.6 5.26-9.96 6.89-4.37 1.63-9.55 2.45-15.54 2.45-5.09-.01-10.06-.64-14.92-1.89zm116.48-60.29v61.26h-16.85v-7.29a23.4 23.4 0 0 1-8.43 6.09c-3.26 1.4-6.79 2.11-10.59 2.11-8.05 0-14.42-2.31-19.13-6.95-4.71-4.63-7.06-11.5-7.06-20.61v-34.61h17.76v32c0 9.87 4.14 14.8 12.41 14.8 4.25 0 7.67-1.38 10.25-4.16 2.58-2.77 3.87-6.89 3.87-12.35v-30.29h17.77zm16.51-23.23h17.76v84.49H416.1v-84.49zm93.94 58.87H463.7c.83 3.8 2.81 6.79 5.92 9 3.11 2.2 6.98 3.3 11.61 3.3 3.19 0 6.01-.47 8.48-1.42 2.47-.95 4.76-2.45 6.89-4.5l9.45 10.25c-5.77 6.6-14.2 9.91-25.28 9.91-6.91 0-13.02-1.35-18.33-4.04-5.31-2.69-9.41-6.43-12.3-11.22-2.89-4.78-4.33-10.21-4.33-16.28 0-6 1.42-11.4 4.27-16.23 2.85-4.82 6.76-8.58 11.73-11.27 4.97-2.69 10.53-4.04 16.68-4.04 6 0 11.42 1.29 16.28 3.87 4.86 2.58 8.67 6.28 11.44 11.1 2.77 4.82 4.16 10.42 4.16 16.79.01.22-.1 1.82-.33 4.78zm-41.56-19.7c-2.73 2.28-4.4 5.39-5.01 9.34h30.17c-.61-3.87-2.28-6.96-5.01-9.28-2.73-2.31-6.07-3.47-10.02-3.47-4.02-.01-7.4 1.13-10.13 3.41z"/>
|
||||||
<style type="text/css">
|
<path d="M144.97 316.25c2.88-4.14 5.7-8.31 8.68-12.38.84-1.14 2.13-1.94 3.22-2.9 8.67 2.77 17.24 5.98 26.06 8.18 7.28 1.81 7.49 1.33 11.08-5.55 9.52-18.28 18.99-36.58 28.42-54.91 3.55-6.9 7.04-13.85 10.34-20.87 1.87-3.99 1-5.28-3.27-5.1-5.07.21-10.13.68-15.19 1.04 1.72-2.35 3.24-4.87 5.2-7.01 4.47-4.88 9.14-9.57 13.74-14.34 1.84-.03 3.68.02 5.52-.1 14.62-1.03 29.24-2.1 43.86-3.16-.08.84-.24 1.68-.24 2.52.01 48.41.03 96.83.05 145.24-15.73.85-30.48.97-47.48-.65-16.01-1.04-30.66-3.54-46.6-5.49-13.64-1.67-26.85-5.2-39.21-11.4-4.77-2.4-5.86-5.41-4.24-10.45.25-.82.05-1.78.06-2.67z" class="st2"/>
|
||||||
.st0{fill:#274872;}
|
<path d="M282.42 346.9c-.02-48.41-.04-96.83-.05-145.24 0-.84.05-1.64.04-2.48 5.63.1 11.47-.06 17.08.32 11.35.78 22.67 1.83 34.01 2.77 2.69 3.09 5.47 6.1 8.05 9.28 3.38 4.17 6.61 8.47 9.9 12.71-6.04-.52-12.07-1.2-18.13-1.49-4.12-.2-4.91 1.24-3.08 4.81 9.87 19.27 19.73 38.54 29.65 57.78 4.02 7.79 8.22 15.49 12.24 23.29 1.46 2.83 3.6 3.9 6.61 3.17 11.52-2.81 23.03-5.68 34.54-8.52 1.8 3.04 3.52 6.13 5.42 9.1.89 1.39 2.13 2.56 3.21 3.83 0 .56-.19 1.22.04 1.66 3.28 6.31-.16 9.95-5.82 12.53-14.18 6.44-29.11 9.85-44.52 11.41-12.89 1.31-25.79 2.51-38.68 3.77-6.24.61-12.47 1.45-18.72 1.79-4.58.24-9.2-.17-13.81-.3l-17.85-.12-.13-.07z" class="st3"/>
|
||||||
.st1{fill:#314A70;}
|
<path d="M413.28 303.3c-11.51 2.84-23.02 5.71-34.54 8.52-3.01.74-5.15-.34-6.61-3.17-4.02-7.79-8.22-15.49-12.24-23.29-9.92-19.24-19.79-38.51-29.65-57.78-1.83-3.57-1.04-5.01 3.08-4.81 6.05.29 12.09.97 18.13 1.49 1.89.4 2.54.15 5.06 3.74 17.1 24.41 37.01 47.73 54.85 71.62.81 1.1 1.28 2.45 1.92 3.68z" class="st2"/>
|
||||||
.st2{fill:#5783AB;}
|
<path d="M155.06 302.38c11.51 2.84 22.26 5.47 33.78 8.28 3.01.74 5.15-.34 6.61-3.17 4.02-7.79 8.22-15.49 12.24-23.29 9.92-19.24 17.3-37.26 26.37-56.7 1.83-3.57.68-4.95-3.44-4.75-6.05.29-10.08.42-16.13.94-2.11 1.25-2.46 1.66-3.84 3.47-18.01 23.75-35.83 47.64-53.67 71.53-.8 1.1-1.28 2.45-1.92 3.69z" class="st3"/>
|
||||||
.st3{fill:#EAECEC;}
|
<path d="M421.92 316.24c0 .56-.19 1.22.04 1.66 3.28 6.31-.16 9.95-5.82 12.53-14.18 6.44-29.11 9.85-44.52 11.41-12.89 1.31-25.79 2.51-38.68 3.77-6.24.61-12.94 1.22-18.94 1.29-4.59.05-8.98.32-13.59.2l-17.85-.12-.12-.08c-15.36.35-28.73.35-46.17-1.19-15.98-1.41-31.97-2.99-47.91-4.95-13.64-1.67-26.85-5.2-39.21-11.4-4.77-2.4-5.86-5.41-4.24-10.45.26-.81.06-1.77.07-2.66-6.55 2.47-11.33 6.45-12.86 13.75-1.74 8.28.69 15.31 5.77 21.67 1.43 1.79 2.4 3.22.07 5.22-.71.61-.81 3.27-.15 3.89 6.36 6.04 13.89 10.11 22.37 12.36 2.35.62 4.12.02 4.62-2.85.11-.64 1.63-1.63 2.27-1.49 8.66 1.96 17.26 4.13 25.91 6.14 1.98.46 2.73 1 1.52 3.01-1.45 2.4-.41 3.92 2 4.93 8.64 3.63 17.82 3.98 26.97 4.34 2.18.08 4.54-.9 3.51-3.88-1.11-3.22.45-3.2 2.83-2.99 8.57.73 17.14 1.44 25.72 1.95 3.13.19 3.98 1.04 2.41 3.98-1.6 2.98-.26 4.76 2.9 4.77 14.82.08 29.65.17 44.46-.08 4.59-.08 5.1-1.29 3.36-5.63-.84-2.1-.97-2.87 1.76-3.02 9.16-.52 18.32-1.21 27.45-2.12 2.5-.25 3.06.34 2.55 2.56-.53 2.31.05 4.05 2.72 4.11 9.52.21 18.91-.53 27.82-4.34 1.95-.83 3.09-2.06 1.71-4.23-1.72-2.71-.09-3.15 2.17-3.67 8.24-1.87 16.46-3.83 24.64-5.93 1.82-.47 3-.77 3.21 1.6.26 2.99 2.1 3.32 4.53 2.61 8.11-2.36 15.55-5.98 21.6-11.99.69-.69 1.03-2.99.55-3.39-3.18-2.71-1.41-4.64.51-6.95 7.99-9.66 9.45-27.91-7.96-34.34z" class="st0"/>
|
||||||
</style>
|
<path d="M324.35 192.94c-6.72-.27-13.4-.35-20.23-.52-7.13-.17-18.9-.51-18.9-.51s-1.27.04-2.44 0c0 0-.63-.01-.63.18-.01-5.67.01-11.83 0-17.5 12.58.95 24.65 1.94 37.19 2.72 1.5.09 3.29-.07 4.8-.12.05 5.24.19 10.5.21 15.75z" class="st3"/>
|
||||||
<path class="st0" d="M243.53,178.65c-0.06-4.5-0.37-9.02,0-13.49c0.1-1.22,2.13-3.09,3.45-3.25c6.99-0.88,14.03-1.47,21.07-1.8
|
<path d="M243.35 193.45c6.72-.27 10.02-.35 16.86-.52 7.13-.17 18.9-.51 18.9-.51s1.27.04 2.44 0c0 0 .63-.53.63-.34.01-5.67-.01-11.83 0-17.5-12.58.95-21.28 1.94-33.82 2.72-1.5.09-3.29-.07-4.8-.12-.05 5.25-.18 11.03-.21 16.27z" class="st2"/>
|
||||||
c2.43-0.12,3.48-1.05,4.29-3.12c2-5.14,4.08-10.25,6.32-15.29c0.86-1.93,0.56-2.83-1.2-4.09c-4.42-3.15-4.97-8.41-1.6-12.08
|
<path d="M327.57 193.15c-1.31-.1-2.62-.17-3.93-.26-13.33-.32-26.66-.63-39.99-.95h-.2c-13.33.32-26.66.63-39.99.95-1.31.08-2.62.15-3.93.26-6.26.5-6.88 1.16-6.73 7.17.02.7.18 1.39.27 2.09 1.91-.03 3.82.02 5.72-.1 14.92-1.02 28.65-2.07 43.57-3.11 14.92 1.04 31.01 2.1 45.93 3.11 1.9.13 3.81.07 5.72.1.09-.7.25-1.39.27-2.09.17-6.01-.46-6.67-6.71-7.17z" class="st0"/>
|
||||||
c3.7-4.04,8.88-4.09,12.65-0.12c3.5,3.68,3.07,8.88-1.39,12.08c-1.93,1.39-2.08,2.44-1.22,4.44c2.19,5.06,3.96,10.31,6.33,15.27
|
|
||||||
c0.65,1.37,2.73,2.73,4.28,2.89c7.57,0.77,15.19,1.17,22.79,1.64c2.69,0.16,4.13,1.28,4.21,4.15c0.1,3.95,0.43,7.89,0.66,11.84
|
|
||||||
c-1.51,0.05-3.03,0.22-4.53,0.13c-12.54-0.76-37.47-2.65-37.47-2.65S254.81,177.52,243.53,178.65z"/>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M73.32,483.91c-5.2-2.69-9.26-6.43-12.18-11.22c-2.92-4.78-4.38-10.21-4.38-16.28c0-6.07,1.46-11.5,4.38-16.28
|
|
||||||
c2.92-4.78,6.98-8.52,12.18-11.22c5.2-2.69,11.06-4.04,17.59-4.04c6.45,0,12.09,1.35,16.91,4.04c4.82,2.7,8.33,6.55,10.53,11.56
|
|
||||||
l-13.78,7.4c-3.19-5.62-7.78-8.43-13.78-8.43c-4.63,0-8.47,1.52-11.5,4.55c-3.04,3.04-4.55,7.17-4.55,12.41
|
|
||||||
c0,5.24,1.52,9.38,4.55,12.41c3.04,3.04,6.87,4.55,11.5,4.55c6.07,0,10.66-2.81,13.78-8.43l13.78,7.52
|
|
||||||
c-2.2,4.86-5.71,8.65-10.53,11.39c-4.82,2.73-10.46,4.1-16.91,4.1C84.38,487.95,78.52,486.6,73.32,483.91z"/>
|
|
||||||
<path class="st1" d="M175.17,431.64c5.08,4.52,7.63,11.33,7.63,20.44v34.96h-16.62v-7.63c-3.34,5.69-9.56,8.54-18.67,8.54
|
|
||||||
c-4.71,0-8.79-0.8-12.24-2.39c-3.46-1.59-6.09-3.79-7.91-6.6c-1.82-2.81-2.73-6-2.73-9.56c0-5.69,2.14-10.17,6.43-13.44
|
|
||||||
c4.29-3.26,10.91-4.9,19.87-4.9h14.12c0-3.87-1.18-6.85-3.53-8.94c-2.35-2.09-5.88-3.13-10.59-3.13c-3.26,0-6.47,0.51-9.62,1.54
|
|
||||||
c-3.15,1.03-5.83,2.41-8.03,4.16l-6.38-12.41c3.34-2.35,7.34-4.17,12.01-5.47c4.67-1.29,9.47-1.94,14.4-1.94
|
|
||||||
C162.8,424.87,170.08,427.13,175.17,431.64z M160.03,473.89c2.35-1.4,4.02-3.47,5.01-6.21v-6.26h-12.18
|
|
||||||
c-7.29,0-10.93,2.39-10.93,7.17c0,2.28,0.89,4.08,2.68,5.41c1.78,1.33,4.23,1.99,7.34,1.99
|
|
||||||
C154.98,475.99,157.67,475.29,160.03,473.89z"/>
|
|
||||||
<path class="st1" d="M250.6,428.8c4.67,2.62,8.33,6.3,10.99,11.04c2.66,4.75,3.99,10.27,3.99,16.57s-1.33,11.82-3.99,16.57
|
|
||||||
c-2.66,4.75-6.32,8.43-10.99,11.04s-9.85,3.93-15.54,3.93c-7.82,0-13.97-2.47-18.45-7.4v28.58h-17.76v-83.35h16.97v7.06
|
|
||||||
c4.4-5.31,10.82-7.97,19.24-7.97C240.76,424.87,245.94,426.18,250.6,428.8z M243.2,468.76c2.92-3.07,4.38-7.19,4.38-12.35
|
|
||||||
s-1.46-9.28-4.38-12.35c-2.92-3.07-6.66-4.61-11.22-4.61s-8.29,1.54-11.22,4.61c-2.92,3.07-4.38,7.19-4.38,12.35
|
|
||||||
s1.46,9.28,4.38,12.35c2.92,3.07,6.66,4.61,11.22,4.61S240.28,471.84,243.2,468.76z"/>
|
|
||||||
<path class="st1" d="M283.11,486.07c-4.86-1.25-8.73-2.83-11.61-4.73l5.92-12.75c2.73,1.75,6.03,3.17,9.91,4.27
|
|
||||||
c3.87,1.1,7.67,1.65,11.39,1.65c7.51,0,11.27-1.86,11.27-5.58c0-1.75-1.03-3-3.07-3.76c-2.05-0.76-5.2-1.4-9.45-1.94
|
|
||||||
c-5.01-0.76-9.15-1.63-12.41-2.62c-3.26-0.99-6.09-2.73-8.48-5.24s-3.59-6.07-3.59-10.7c0-3.87,1.12-7.3,3.36-10.3
|
|
||||||
c2.24-3,5.5-5.33,9.79-7c4.29-1.67,9.35-2.5,15.2-2.5c4.33,0,8.63,0.48,12.92,1.42c4.29,0.95,7.84,2.26,10.65,3.93l-5.92,12.64
|
|
||||||
c-5.39-3.04-11.27-4.55-17.65-4.55c-3.8,0-6.64,0.53-8.54,1.59c-1.9,1.06-2.85,2.43-2.85,4.1c0,1.9,1.02,3.23,3.07,3.99
|
|
||||||
c2.05,0.76,5.31,1.48,9.79,2.16c5.01,0.84,9.11,1.73,12.3,2.68c3.19,0.95,5.96,2.68,8.31,5.18c2.35,2.5,3.53,6,3.53,10.48
|
|
||||||
c0,3.8-1.14,7.17-3.42,10.13c-2.28,2.96-5.6,5.26-9.96,6.89c-4.37,1.63-9.55,2.45-15.54,2.45
|
|
||||||
C292.94,487.95,287.97,487.32,283.11,486.07z"/>
|
|
||||||
<path class="st1" d="M399.59,425.78v61.26h-16.85v-7.29c-2.35,2.66-5.16,4.69-8.43,6.09c-3.26,1.4-6.79,2.11-10.59,2.11
|
|
||||||
c-8.05,0-14.42-2.31-19.13-6.95c-4.71-4.63-7.06-11.5-7.06-20.61v-34.61h17.76v32c0,9.87,4.14,14.8,12.41,14.8
|
|
||||||
c4.25,0,7.67-1.38,10.25-4.16c2.58-2.77,3.87-6.89,3.87-12.35v-30.29H399.59z"/>
|
|
||||||
<path class="st1" d="M416.1,402.55h17.76v84.49H416.1V402.55z"/>
|
|
||||||
<path class="st1" d="M510.04,461.42H463.7c0.83,3.8,2.81,6.79,5.92,9c3.11,2.2,6.98,3.3,11.61,3.3c3.19,0,6.01-0.47,8.48-1.42
|
|
||||||
c2.47-0.95,4.76-2.45,6.89-4.5l9.45,10.25c-5.77,6.6-14.2,9.91-25.28,9.91c-6.91,0-13.02-1.35-18.33-4.04
|
|
||||||
c-5.31-2.69-9.41-6.43-12.3-11.22c-2.89-4.78-4.33-10.21-4.33-16.28c0-6,1.42-11.4,4.27-16.23c2.85-4.82,6.76-8.58,11.73-11.27
|
|
||||||
c4.97-2.69,10.53-4.04,16.68-4.04c6,0,11.42,1.29,16.28,3.87c4.86,2.58,8.67,6.28,11.44,11.1c2.77,4.82,4.16,10.42,4.16,16.79
|
|
||||||
C510.38,456.86,510.27,458.46,510.04,461.42z M468.48,441.72c-2.73,2.28-4.4,5.39-5.01,9.34h30.17c-0.61-3.87-2.28-6.96-5.01-9.28
|
|
||||||
c-2.73-2.31-6.07-3.47-10.02-3.47C474.59,438.3,471.21,439.44,468.48,441.72z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path class="st2" d="M144.97,316.25c2.88-4.14,5.7-8.31,8.68-12.38c0.84-1.14,2.13-1.94,3.22-2.9c8.67,2.77,17.24,5.98,26.06,8.18
|
|
||||||
c7.28,1.81,7.49,1.33,11.08-5.55c9.52-18.28,18.99-36.58,28.42-54.91c3.55-6.9,7.04-13.85,10.34-20.87c1.87-3.99,1-5.28-3.27-5.1
|
|
||||||
c-5.07,0.21-10.13,0.68-15.19,1.04c1.72-2.35,3.24-4.87,5.2-7.01c4.47-4.88,9.14-9.57,13.74-14.34c1.84-0.03,3.68,0.02,5.52-0.1
|
|
||||||
c14.62-1.03,29.24-2.1,43.86-3.16c-0.08,0.84-0.24,1.68-0.24,2.52c0.01,48.41,0.03,96.83,0.05,145.24
|
|
||||||
c-15.73,0.85-30.48,0.97-47.48-0.65c-16.01-1.04-30.66-3.54-46.6-5.49c-13.64-1.67-26.85-5.2-39.21-11.4
|
|
||||||
c-4.77-2.4-5.86-5.41-4.24-10.45C145.16,318.1,144.96,317.14,144.97,316.25z"/>
|
|
||||||
<path class="st3" d="M282.42,346.9c-0.02-48.41-0.04-96.83-0.05-145.24c0-0.84,0.05-1.64,0.04-2.48
|
|
||||||
c5.63,0.1,11.47-0.06,17.08,0.32c11.35,0.78,22.67,1.83,34.01,2.77c2.69,3.09,5.47,6.1,8.05,9.28c3.38,4.17,6.61,8.47,9.9,12.71
|
|
||||||
c-6.04-0.52-12.07-1.2-18.13-1.49c-4.12-0.2-4.91,1.24-3.08,4.81c9.87,19.27,19.73,38.54,29.65,57.78
|
|
||||||
c4.02,7.79,8.22,15.49,12.24,23.29c1.46,2.83,3.6,3.9,6.61,3.17c11.52-2.81,23.03-5.68,34.54-8.52c1.8,3.04,3.52,6.13,5.42,9.1
|
|
||||||
c0.89,1.39,2.13,2.56,3.21,3.83c0,0.56-0.19,1.22,0.04,1.66c3.28,6.31-0.16,9.95-5.82,12.53c-14.18,6.44-29.11,9.85-44.52,11.41
|
|
||||||
c-12.89,1.31-25.79,2.51-38.68,3.77c-6.24,0.61-12.47,1.45-18.72,1.79c-4.58,0.24-9.2-0.17-13.81-0.3
|
|
||||||
c-5.95-0.04-11.9-0.08-17.85-0.12L282.42,346.9z"/>
|
|
||||||
<path class="st2" d="M413.28,303.3c-11.51,2.84-23.02,5.71-34.54,8.52c-3.01,0.74-5.15-0.34-6.61-3.17
|
|
||||||
c-4.02-7.79-8.22-15.49-12.24-23.29c-9.92-19.24-19.79-38.51-29.65-57.78c-1.83-3.57-1.04-5.01,3.08-4.81
|
|
||||||
c6.05,0.29,12.09,0.97,18.13,1.49c1.89,0.4,2.54,0.15,5.06,3.74c17.1,24.41,37.01,47.73,54.85,71.62
|
|
||||||
C412.17,300.72,412.64,302.07,413.28,303.3z"/>
|
|
||||||
<path class="st3" d="M155.06,302.38c11.51,2.84,22.26,5.47,33.78,8.28c3.01,0.74,5.15-0.34,6.61-3.17
|
|
||||||
c4.02-7.79,8.22-15.49,12.24-23.29c9.92-19.24,17.3-37.26,26.37-56.7c1.83-3.57,0.68-4.95-3.44-4.75
|
|
||||||
c-6.05,0.29-10.08,0.42-16.13,0.94c-2.11,1.25-2.46,1.66-3.84,3.47c-18.01,23.75-35.83,47.64-53.67,71.53
|
|
||||||
C156.18,299.79,155.7,301.14,155.06,302.38z"/>
|
|
||||||
<path class="st0" d="M421.92,316.24c0,0.56-0.19,1.22,0.04,1.66c3.28,6.31-0.16,9.95-5.82,12.53
|
|
||||||
c-14.18,6.44-29.11,9.85-44.52,11.41c-12.89,1.31-25.79,2.51-38.68,3.77c-6.24,0.61-12.94,1.22-18.94,1.29
|
|
||||||
c-4.59,0.05-8.98,0.32-13.59,0.2c-5.95-0.04-11.9-0.08-17.85-0.12c0,0-0.12-0.08-0.12-0.08c-15.36,0.35-28.73,0.35-46.17-1.19
|
|
||||||
c-15.98-1.41-31.97-2.99-47.91-4.95c-13.64-1.67-26.85-5.2-39.21-11.4c-4.77-2.4-5.86-5.41-4.24-10.45
|
|
||||||
c0.26-0.81,0.06-1.77,0.07-2.66c-6.55,2.47-11.33,6.45-12.86,13.75c-1.74,8.28,0.69,15.31,5.77,21.67
|
|
||||||
c1.43,1.79,2.4,3.22,0.07,5.22c-0.71,0.61-0.81,3.27-0.15,3.89c6.36,6.04,13.89,10.11,22.37,12.36c2.35,0.62,4.12,0.02,4.62-2.85
|
|
||||||
c0.11-0.64,1.63-1.63,2.27-1.49c8.66,1.96,17.26,4.13,25.91,6.14c1.98,0.46,2.73,1,1.52,3.01c-1.45,2.4-0.41,3.92,2,4.93
|
|
||||||
c8.64,3.63,17.82,3.98,26.97,4.34c2.18,0.08,4.54-0.9,3.51-3.88c-1.11-3.22,0.45-3.2,2.83-2.99c8.57,0.73,17.14,1.44,25.72,1.95
|
|
||||||
c3.13,0.19,3.98,1.04,2.41,3.98c-1.6,2.98-0.26,4.76,2.9,4.77c14.82,0.08,29.65,0.17,44.46-0.08c4.59-0.08,5.1-1.29,3.36-5.63
|
|
||||||
c-0.84-2.1-0.97-2.87,1.76-3.02c9.16-0.52,18.32-1.21,27.45-2.12c2.5-0.25,3.06,0.34,2.55,2.56c-0.53,2.31,0.05,4.05,2.72,4.11
|
|
||||||
c9.52,0.21,18.91-0.53,27.82-4.34c1.95-0.83,3.09-2.06,1.71-4.23c-1.72-2.71-0.09-3.15,2.17-3.67c8.24-1.87,16.46-3.83,24.64-5.93
|
|
||||||
c1.82-0.47,3-0.77,3.21,1.6c0.26,2.99,2.1,3.32,4.53,2.61c8.11-2.36,15.55-5.98,21.6-11.99c0.69-0.69,1.03-2.99,0.55-3.39
|
|
||||||
c-3.18-2.71-1.41-4.64,0.51-6.95C437.87,340.92,439.33,322.67,421.92,316.24z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<path class="st3" d="M324.35,192.94c-6.72-0.27-13.4-0.35-20.23-0.52c-7.13-0.17-18.9-0.51-18.9-0.51s-1.27,0.04-2.44,0
|
|
||||||
c0,0-0.63-0.01-0.63,0.18c-0.01-5.67,0.01-11.83,0-17.5c12.58,0.95,24.65,1.94,37.19,2.72c1.5,0.09,3.29-0.07,4.8-0.12
|
|
||||||
C324.19,182.43,324.33,187.69,324.35,192.94z"/>
|
|
||||||
<path class="st2" d="M243.35,193.45c6.72-0.27,10.02-0.35,16.86-0.52c7.13-0.17,18.9-0.51,18.9-0.51s1.27,0.04,2.44,0
|
|
||||||
c0,0,0.63-0.53,0.63-0.34c0.01-5.67-0.01-11.83,0-17.5c-12.58,0.95-21.28,1.94-33.82,2.72c-1.5,0.09-3.29-0.07-4.8-0.12
|
|
||||||
C243.51,182.43,243.38,188.21,243.35,193.45z"/>
|
|
||||||
<path class="st0" d="M327.57,193.15c-1.31-0.1-2.62-0.17-3.93-0.26c-13.33-0.32-26.66-0.63-39.99-0.95v0c-0.03,0-0.06,0-0.1,0
|
|
||||||
c-0.03,0-0.06,0-0.1,0v0c-13.33,0.32-26.66,0.63-39.99,0.95c-1.31,0.08-2.62,0.15-3.93,0.26c-6.26,0.5-6.88,1.16-6.73,7.17
|
|
||||||
c0.02,0.7,0.18,1.39,0.27,2.09c1.91-0.03,3.82,0.02,5.72-0.1c14.92-1.02,28.65-2.07,43.57-3.11c14.92,1.04,31.01,2.1,45.93,3.11
|
|
||||||
c1.9,0.13,3.81,0.07,5.72,0.1c0.09-0.7,0.25-1.39,0.27-2.09C334.45,194.31,333.82,193.65,327.57,193.15z"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 7.9 KiB |
@@ -1,6 +1,6 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
- name: capsule-proxy
|
- name: capsule-proxy
|
||||||
repository: oci://ghcr.io/projectcapsule/charts
|
repository: oci://ghcr.io/projectcapsule/charts
|
||||||
version: 0.9.1
|
version: 0.10.0
|
||||||
digest: sha256:509f9d3d3c0181d9e5a410524d4767a687d8176620d24f7e460f354f18c0a5f8
|
digest: sha256:b268fe0a87e4fa4d0196e5dac82c7e8ae20e96053f5ca860b1f7c44e3a357406
|
||||||
generated: "2025-02-10T13:33:33.19014368Z"
|
generated: "2025-12-09T15:58:45.796317945Z"
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
type: application
|
type: application
|
||||||
description: A Helm chart to deploy the Capsule Operator for easily implementing,
|
description: A Helm chart to deploy the Capsule Operator for easily implementing,
|
||||||
managing, and maintaining mutitenancy and access control in Kubernetes.
|
managing, and maintaining multitenancy and access control in Kubernetes.
|
||||||
home: https://github.com/projectcapsule/capsule
|
home: https://projectcapsule.dev/
|
||||||
icon: https://github.com/projectcapsule/capsule/raw/main/assets/logo/capsule_small.png
|
icon: https://github.com/projectcapsule/capsule/raw/main/assets/logo/capsule_small.png
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: capsule-proxy
|
- name: capsule-proxy
|
||||||
version: 0.9.1
|
version: 0.10.0
|
||||||
repository: "oci://ghcr.io/projectcapsule/charts"
|
repository: "oci://ghcr.io/projectcapsule/charts"
|
||||||
condition: proxy.enabled
|
condition: proxy.enabled
|
||||||
alias: proxy
|
alias: proxy
|
||||||
@@ -41,4 +41,4 @@ annotations:
|
|||||||
url: https://projectcapsule.dev/
|
url: https://projectcapsule.dev/
|
||||||
artifacthub.io/changes: |
|
artifacthub.io/changes: |
|
||||||
- kind: added
|
- kind: added
|
||||||
description: oci chart reference
|
description: added toggles for podSecurityContexts and securityContexts
|
||||||
|
|||||||
@@ -1,20 +1,8 @@
|
|||||||
# Deploying the Capsule Operator
|
# Deploying the Capsule Operator
|
||||||
|
|
||||||
Use the Capsule Operator for easily implementing, managing, and maintaining multitenancy and access control in Kubernetes.
|
Use the Capsule Operator for easily implementing, managing, and maintaining multitenancy and access control in Kubernetes. Please read our installation guide:
|
||||||
|
|
||||||
## Requirements
|
* [https://projectcapsule.dev/docs/operating/setup/installation/](https://projectcapsule.dev/docs/operating/setup/installation/)
|
||||||
|
|
||||||
* [Helm 3](https://github.com/helm/helm/releases) is required when installing the Capsule Operator chart. Follow Helm’s official [steps](https://helm.sh/docs/intro/install/) for installing helm on your particular operating system.
|
|
||||||
|
|
||||||
* A Kubernetes cluster 1.16+ with following [Admission Controllers](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/) enabled:
|
|
||||||
|
|
||||||
* PodNodeSelector
|
|
||||||
* LimitRanger
|
|
||||||
* ResourceQuota
|
|
||||||
* MutatingAdmissionWebhook
|
|
||||||
* ValidatingAdmissionWebhook
|
|
||||||
|
|
||||||
* A [`kubeconfig`](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/) file accessing the Kubernetes cluster with cluster admin permissions.
|
|
||||||
|
|
||||||
## Major Changes
|
## Major Changes
|
||||||
|
|
||||||
@@ -33,65 +21,16 @@ The following Values have changed key or Value:
|
|||||||
* `mutatingWebhooksTimeoutSeconds` has moved to `webhooks.mutatingWebhooksTimeoutSeconds`
|
* `mutatingWebhooksTimeoutSeconds` has moved to `webhooks.mutatingWebhooksTimeoutSeconds`
|
||||||
* `validatingWebhooksTimeoutSeconds` has moved to `webhooks.validatingWebhooksTimeoutSeconds`
|
* `validatingWebhooksTimeoutSeconds` has moved to `webhooks.validatingWebhooksTimeoutSeconds`
|
||||||
|
|
||||||
## Installation
|
## Values
|
||||||
|
|
||||||
**When using OCI we recommend our dedicated [OCI Repository](https://artifacthub.io/packages/helm/capsule/capsule) for this chart**
|
|
||||||
|
|
||||||
The Capsule Operator requires it's CRDs to be installed before the operator itself. Since the Helm CRD lifecycle has limitations, we recommend to install the CRDs separately. Our chart supports the installation of crds via a dedicated Release.
|
|
||||||
The Capsule Operator Chart can be used to instantly deploy the Capsule Operator on your Kubernetes cluster.
|
|
||||||
|
|
||||||
1. Add this repository:
|
|
||||||
|
|
||||||
$ helm repo add projectcapsule https://projectcapsule.github.io/charts
|
|
||||||
|
|
||||||
2. Install Capsule:
|
|
||||||
|
|
||||||
$ helm install capsule projectcapsule/capsule --version 0.7.0 -n capsule-system --create-namespace
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
$ helm install capsule oci://ghcr.io/projectcapsule/charts/capsule --version 0.7.0 -n capsule-system --create-namespace
|
|
||||||
|
|
||||||
3. Show the status:
|
|
||||||
|
|
||||||
$ helm status capsule -n capsule-system
|
|
||||||
|
|
||||||
4. Upgrade the Chart
|
|
||||||
|
|
||||||
$ helm upgrade capsule projectcapsule/capsule -n capsule-system
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
$ helm upgrade capsule oci://ghcr.io/projectcapsule/charts/capsule --version 0.4.7
|
|
||||||
|
|
||||||
5. Uninstall the Chart
|
|
||||||
|
|
||||||
$ helm uninstall capsule -n capsule-system
|
|
||||||
|
|
||||||
## Customize the installation
|
|
||||||
|
|
||||||
There are two methods for specifying overrides of values during chart installation: `--values` and `--set`.
|
|
||||||
|
|
||||||
The `--values` option is the preferred method because it allows you to keep your overrides in a YAML file, rather than specifying them all on the command line. Create a copy of the YAML file `values.yaml` and add your overrides to it.
|
|
||||||
|
|
||||||
Specify your overrides file when you install the chart:
|
|
||||||
|
|
||||||
$ helm install capsule capsule-helm-chart --values myvalues.yaml -n capsule-system
|
|
||||||
|
|
||||||
The values in your overrides file `myvalues.yaml` will override their counterparts in the chart's values.yaml file. Any values in `values.yaml` that weren’t overridden will keep their defaults.
|
|
||||||
|
|
||||||
If you only need to make minor customizations, you can specify them on the command line by using the `--set` option. For example:
|
|
||||||
|
|
||||||
$ helm install capsule capsule-helm-chart --set manager.options.forceTenantPrefix=false -n capsule-system
|
|
||||||
|
|
||||||
Here the values you can override:
|
|
||||||
|
|
||||||
### CustomResourceDefinition Lifecycle
|
### CustomResourceDefinition Lifecycle
|
||||||
|
|
||||||
| Key | Type | Default | Description |
|
| Key | Type | Default | Description |
|
||||||
|-----|------|---------|-------------|
|
|-----|------|---------|-------------|
|
||||||
| crds.annnotations | object | `{}` | Extra Annotations for CRDs |
|
| crds.annnotations | object | `{}` | Extra Annotations for CRDs |
|
||||||
|
| crds.createConfig | bool | `false` | Create additionally CapsuleConfiguration even if CRDs are exclusive |
|
||||||
| crds.exclusive | bool | `false` | Only install the CRDs, no other primitives |
|
| crds.exclusive | bool | `false` | Only install the CRDs, no other primitives |
|
||||||
|
| crds.inline | bool | `false` | |
|
||||||
| crds.install | bool | `true` | Install the CustomResourceDefinitions (This also manages the lifecycle of the CRDs for update operations) |
|
| crds.install | bool | `true` | Install the CustomResourceDefinitions (This also manages the lifecycle of the CRDs for update operations) |
|
||||||
| crds.labels | object | `{}` | Extra Labels for CRDs |
|
| crds.labels | object | `{}` | Extra Labels for CRDs |
|
||||||
|
|
||||||
@@ -100,22 +39,27 @@ Here the values you can override:
|
|||||||
| Key | Type | Default | Description |
|
| Key | Type | Default | Description |
|
||||||
|-----|------|---------|-------------|
|
|-----|------|---------|-------------|
|
||||||
| global.jobs.kubectl.affinity | object | `{}` | Set affinity rules |
|
| global.jobs.kubectl.affinity | object | `{}` | Set affinity rules |
|
||||||
| global.jobs.kubectl.annotations | object | `{}` | Annotations to add to the certgen job. |
|
| global.jobs.kubectl.annotations | object | `{}` | Annotations to add to the job. |
|
||||||
| global.jobs.kubectl.backoffLimit | int | `4` | Backofflimit for jobs |
|
| global.jobs.kubectl.backoffLimit | int | `4` | Backofflimit for jobs |
|
||||||
| global.jobs.kubectl.image.pullPolicy | string | `"IfNotPresent"` | Set the image pull policy of the helm chart job |
|
| global.jobs.kubectl.image.pullPolicy | string | `"IfNotPresent"` | Set the image pull policy of the helm chart job |
|
||||||
| global.jobs.kubectl.image.registry | string | `"docker.io"` | Set the image repository of the helm chart job |
|
| global.jobs.kubectl.image.registry | string | `"docker.io"` | Set the image repository of the helm chart job |
|
||||||
| global.jobs.kubectl.image.repository | string | `"clastix/kubectl"` | Set the image repository of the helm chart job |
|
| global.jobs.kubectl.image.repository | string | `"clastix/kubectl"` | Set the image repository of the helm chart job |
|
||||||
| global.jobs.kubectl.image.tag | string | `""` | Set the image tag of the helm chart job |
|
| global.jobs.kubectl.image.tag | string | `""` | Set the image tag of the helm chart job |
|
||||||
| global.jobs.kubectl.imagePullSecrets | list | `[]` | ImagePullSecrets |
|
| global.jobs.kubectl.imagePullSecrets | list | `[]` | ImagePullSecrets |
|
||||||
|
| global.jobs.kubectl.labels | object | `{}` | Labels to add to the job. |
|
||||||
| global.jobs.kubectl.nodeSelector | object | `{}` | Set the node selector |
|
| global.jobs.kubectl.nodeSelector | object | `{}` | Set the node selector |
|
||||||
| global.jobs.kubectl.podSecurityContext | object | `{"seccompProfile":{"type":"RuntimeDefault"}}` | Security context for the job pods. |
|
| global.jobs.kubectl.podAnnotations | object | `{}` | Annotations to add to the job pod |
|
||||||
|
| global.jobs.kubectl.podLabels | object | `{}` | Labels to add to the job pod |
|
||||||
|
| global.jobs.kubectl.podSecurityContext | object | `{"enabled":true,"seccompProfile":{"type":"RuntimeDefault"}}` | Security context for the job pods. |
|
||||||
| global.jobs.kubectl.priorityClassName | string | `""` | Set a pod priorityClassName |
|
| global.jobs.kubectl.priorityClassName | string | `""` | Set a pod priorityClassName |
|
||||||
| global.jobs.kubectl.resources | object | `{}` | Job resources |
|
| global.jobs.kubectl.resources | object | `{}` | Job resources |
|
||||||
| global.jobs.kubectl.restartPolicy | string | `"Never"` | Set the restartPolicy |
|
| global.jobs.kubectl.restartPolicy | string | `"Never"` | Set the restartPolicy |
|
||||||
| global.jobs.kubectl.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true,"runAsGroup":1002,"runAsNonRoot":true,"runAsUser":1002}` | Security context for the job containers. |
|
| global.jobs.kubectl.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"enabled":true,"readOnlyRootFilesystem":true,"runAsGroup":1002,"runAsNonRoot":true,"runAsUser":1002}` | Security context for the job containers. |
|
||||||
| global.jobs.kubectl.tolerations | list | `[]` | Set list of tolerations |
|
| global.jobs.kubectl.tolerations | list | `[]` | Set list of tolerations |
|
||||||
| global.jobs.kubectl.topologySpreadConstraints | list | `[]` | Set Topology Spread Constraints |
|
| global.jobs.kubectl.topologySpreadConstraints | list | `[]` | Set Topology Spread Constraints |
|
||||||
| global.jobs.kubectl.ttlSecondsAfterFinished | int | `60` | Sets the ttl in seconds after a finished certgen job is deleted. Set to -1 to never delete. |
|
| global.jobs.kubectl.ttlSecondsAfterFinished | int | `60` | Sets the ttl in seconds after a finished certgen job is deleted. Set to -1 to never delete. |
|
||||||
|
| global.jobs.postInstall.enabled | bool | `true` | Enable Post Install Job |
|
||||||
|
| global.jobs.preDelete.enabled | bool | `true` | Enable Pre Delete Job |
|
||||||
|
|
||||||
### General Parameters
|
### General Parameters
|
||||||
|
|
||||||
@@ -123,24 +67,31 @@ Here the values you can override:
|
|||||||
|-----|------|---------|-------------|
|
|-----|------|---------|-------------|
|
||||||
| affinity | object | `{}` | Set affinity rules for the Capsule pod |
|
| affinity | object | `{}` | Set affinity rules for the Capsule pod |
|
||||||
| certManager.additionalSANS | list | `[]` | Specify additional SANS to add to the certificate |
|
| certManager.additionalSANS | list | `[]` | Specify additional SANS to add to the certificate |
|
||||||
| certManager.generateCertificates | bool | `false` | Specifies whether capsule webhooks certificates should be generated using cert-manager |
|
| certManager.generateCertificates | bool | `true` | Specifies whether capsule webhooks certificates should be generated using cert-manager |
|
||||||
| customAnnotations | object | `{}` | Additional annotations which will be added to all resources created by Capsule helm chart |
|
| customAnnotations | object | `{}` | Additional annotations which will be added to all resources created by Capsule helm chart |
|
||||||
| customLabels | object | `{}` | Additional labels which will be added to all resources created by Capsule helm chart |
|
| customLabels | object | `{}` | Additional labels which will be added to all resources created by Capsule helm chart |
|
||||||
|
| extraManifests | list | `[]` | Array of additional resources to be created alongside Capsule helm chart |
|
||||||
| imagePullSecrets | list | `[]` | Configuration for `imagePullSecrets` so that you can use a private images registry. |
|
| imagePullSecrets | list | `[]` | Configuration for `imagePullSecrets` so that you can use a private images registry. |
|
||||||
| jobs | object | `{}` | Deprecated, use .global.jobs.kubectl instead |
|
| jobs | object | `{}` | Deprecated, use .global.jobs.kubectl instead |
|
||||||
| nodeSelector | object | `{}` | Set the node selector for the Capsule pod |
|
| nodeSelector | object | `{}` | Set the node selector for the Capsule pod |
|
||||||
| podAnnotations | object | `{}` | Annotations to add to the capsule pod. |
|
| podAnnotations | object | `{}` | Annotations to add to the capsule pod. |
|
||||||
| podSecurityContext | object | `{"runAsGroup":1002,"runAsNonRoot":true,"runAsUser":1002,"seccompProfile":{"type":"RuntimeDefault"}}` | Set the securityContext for the Capsule pod |
|
| podLabels | object | `{}` | Labels to add to the capsule pod. |
|
||||||
|
| podSecurityContext | object | `{"enabled":true,"runAsGroup":1002,"runAsNonRoot":true,"runAsUser":1002,"seccompProfile":{"type":"RuntimeDefault"}}` | Set the securityContext for the Capsule pod |
|
||||||
| ports | list | `[]` | Set additional ports for the deployment |
|
| ports | list | `[]` | Set additional ports for the deployment |
|
||||||
| priorityClassName | string | `""` | Set the priority class name of the Capsule pod |
|
| priorityClassName | string | `""` | Set the priority class name of the Capsule pod |
|
||||||
| proxy.enabled | bool | `false` | Enable Installation of Capsule Proxy |
|
| proxy.enabled | bool | `false` | Enable Installation of Capsule Proxy |
|
||||||
|
| rbac.resourcepoolclaims.create | bool | `false` | |
|
||||||
|
| rbac.resourcepoolclaims.labels."rbac.authorization.k8s.io/aggregate-to-admin" | string | `"true"` | |
|
||||||
|
| rbac.resources.create | bool | `false` | |
|
||||||
|
| rbac.resources.labels."rbac.authorization.k8s.io/aggregate-to-admin" | string | `"true"` | |
|
||||||
| replicaCount | int | `1` | Set the replica count for capsule pod |
|
| replicaCount | int | `1` | Set the replica count for capsule pod |
|
||||||
| securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true}` | Set the securityContext for the Capsule container |
|
| securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"enabled":true,"readOnlyRootFilesystem":true}` | Set the securityContext for the Capsule container |
|
||||||
| serviceAccount.annotations | object | `{}` | Annotations to add to the service account. |
|
| serviceAccount.annotations | object | `{}` | Annotations to add to the service account. |
|
||||||
| serviceAccount.create | bool | `true` | Specifies whether a service account should be created. |
|
| serviceAccount.create | bool | `true` | Specifies whether a service account should be created. |
|
||||||
|
| serviceAccount.imagePullSecrets | list | `[]` | |
|
||||||
| serviceAccount.name | string | `""` | The name of the service account to use. If not set and `serviceAccount.create=true`, a name is generated using the fullname template |
|
| serviceAccount.name | string | `""` | The name of the service account to use. If not set and `serviceAccount.create=true`, a name is generated using the fullname template |
|
||||||
| tls.create | bool | `true` | When cert-manager is disabled, Capsule will generate the TLS certificate for webhook and CRDs conversion. |
|
| tls.create | bool | `false` | When cert-manager is disabled, Capsule will generate the TLS certificate for webhook and CRDs conversion. |
|
||||||
| tls.enableController | bool | `true` | Start the Capsule controller that injects the CA into mutating and validating webhooks, and CRD as well. |
|
| tls.enableController | bool | `false` | Start the Capsule controller that injects the CA into mutating and validating webhooks, and CRD as well. |
|
||||||
| tls.name | string | `""` | Override name of the Capsule TLS Secret name when externally managed. |
|
| tls.name | string | `""` | Override name of the Capsule TLS Secret name when externally managed. |
|
||||||
| tolerations | list | `[]` | Set list of tolerations for the Capsule pod |
|
| tolerations | list | `[]` | Set list of tolerations for the Capsule pod |
|
||||||
| topologySpreadConstraints | list | `[]` | Set topology spread constraints for the Capsule pod |
|
| topologySpreadConstraints | list | `[]` | Set topology spread constraints for the Capsule pod |
|
||||||
@@ -149,21 +100,41 @@ Here the values you can override:
|
|||||||
|
|
||||||
| Key | Type | Default | Description |
|
| Key | Type | Default | Description |
|
||||||
|-----|------|---------|-------------|
|
|-----|------|---------|-------------|
|
||||||
|
| manager.daemonsetStrategy | object | `{"type":"RollingUpdate"}` | [Daemonset Strategy](https://kubernetes.io/docs/tasks/manage-daemon/update-daemon-set/#creating-a-daemonset-with-rollingupdate-update-strategy) |
|
||||||
|
| manager.deploymentStrategy | object | `{"type":"RollingUpdate"}` | [Deployment Strategy](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy) |
|
||||||
|
| manager.env | list | `[]` | Additional Environment Variables |
|
||||||
|
| manager.extraArgs | list | `["--enable-leader-election=true"]` | A list of extra arguments for the capsule controller |
|
||||||
| manager.hostNetwork | bool | `false` | Specifies if the container should be started in hostNetwork mode. Required for use in some managed kubernetes clusters (such as AWS EKS) with custom CNI (such as calico), because control-plane managed by AWS cannot communicate with pods' IP CIDR and admission webhooks are not working |
|
| manager.hostNetwork | bool | `false` | Specifies if the container should be started in hostNetwork mode. Required for use in some managed kubernetes clusters (such as AWS EKS) with custom CNI (such as calico), because control-plane managed by AWS cannot communicate with pods' IP CIDR and admission webhooks are not working |
|
||||||
| manager.hostPID | bool | `false` | Specifies if the container should be started in hostPID mode. |
|
| manager.hostPID | bool | `false` | Specifies if the container should be started in hostPID mode. |
|
||||||
|
| manager.hostUsers | bool | `true` | Don't use Host Users (User Namespaces) |
|
||||||
| manager.image.pullPolicy | string | `"IfNotPresent"` | Set the image pull policy. |
|
| manager.image.pullPolicy | string | `"IfNotPresent"` | Set the image pull policy. |
|
||||||
| manager.image.registry | string | `"ghcr.io"` | Set the image registry of capsule. |
|
| manager.image.registry | string | `"ghcr.io"` | Set the image registry of capsule. |
|
||||||
| manager.image.repository | string | `"projectcapsule/capsule"` | Set the image repository of capsule. |
|
| manager.image.repository | string | `"projectcapsule/capsule"` | Set the image repository of capsule. |
|
||||||
| manager.image.tag | string | `""` | Overrides the image tag whose default is the chart appVersion. |
|
| manager.image.tag | string | `""` | Overrides the image tag whose default is the chart appVersion. |
|
||||||
| manager.kind | string | `"Deployment"` | Set the controller deployment mode as `Deployment` or `DaemonSet`. |
|
| manager.kind | string | `"Deployment"` | Set the controller deployment mode as `Deployment` or `DaemonSet`. |
|
||||||
| manager.livenessProbe | object | `{"httpGet":{"path":"/healthz","port":10080}}` | Configure the liveness probe using Deployment probe spec |
|
| manager.livenessProbe | object | `{"httpGet":{"path":"/healthz","port":10080}}` | Configure the liveness probe using Deployment probe spec |
|
||||||
|
| manager.options.administrators | list | `[]` | Define entities which can act as Administrators in the capsule construct These entities are automatically owners for all existing tenants. Meaning they can add namespaces to any tenant. However they must be specific by using the capsule label for interacting with namespaces. Because if that label is not defined, it's assumed that namespace interaction was not targeted towards a tenant and will therefor be ignored by capsule. May also be handy in GitOps scenarios where certain service accounts need to be able to manage namespaces for all tenants. |
|
||||||
|
| manager.options.allowServiceAccountPromotion | bool | `false` | ServiceAccounts within tenant namespaces can be promoted to owners of the given tenant this can be achieved by labeling the serviceaccount and then they are considered owners. This can only be done by other owners of the tenant. However ServiceAccounts which have been promoted to owner can not promote further serviceAccounts. |
|
||||||
|
| manager.options.annotations | object | `{}` | Additional annotations to add to the CapsuleConfiguration resource |
|
||||||
|
| manager.options.cacheInvalidation | string | `"24h0m0s"` | Duration after which the in-memory cache is invalidated (based on usaage) and re-fetched from the API server |
|
||||||
| manager.options.capsuleConfiguration | string | `"default"` | Change the default name of the capsule configuration name |
|
| manager.options.capsuleConfiguration | string | `"default"` | Change the default name of the capsule configuration name |
|
||||||
| manager.options.capsuleUserGroups | list | `["projectcapsule.dev"]` | Override the Capsule user groups |
|
| manager.options.capsuleUserGroups | list | `[]` | DEPRECATED: use users properties. Names of the users considered as Capsule users. |
|
||||||
|
| manager.options.createConfiguration | bool | `true` | Create Configuration |
|
||||||
| manager.options.forceTenantPrefix | bool | `false` | Boolean, enforces the Tenant owner, during Namespace creation, to name it using the selected Tenant name as prefix, separated by a dash |
|
| manager.options.forceTenantPrefix | bool | `false` | Boolean, enforces the Tenant owner, during Namespace creation, to name it using the selected Tenant name as prefix, separated by a dash |
|
||||||
| manager.options.generateCertificates | bool | `true` | Specifies whether capsule webhooks certificates should be generated by capsule operator |
|
| manager.options.generateCertificates | bool | `true` | Specifies whether capsule webhooks certificates should be generated by capsule operator |
|
||||||
| manager.options.logLevel | string | `"4"` | Set the log verbosity of the capsule with a value from 1 to 10 |
|
| manager.options.ignoreUserWithGroups | list | `[]` | Define groups which when found in the request of a user will be ignored by the Capsule this might be useful if you have one group where all the users are in, but you want to separate administrators from normal users with additional groups. |
|
||||||
|
| manager.options.labels | object | `{}` | Additional labels to add to the CapsuleConfiguration resource |
|
||||||
|
| manager.options.logLevel | string | `"info"` | Set the log verbosity of the capsule with a value from 1 to 5 |
|
||||||
| manager.options.nodeMetadata | object | `{"forbiddenAnnotations":{"denied":[],"deniedRegex":""},"forbiddenLabels":{"denied":[],"deniedRegex":""}}` | Allows to set the forbidden metadata for the worker nodes that could be patched by a Tenant |
|
| manager.options.nodeMetadata | object | `{"forbiddenAnnotations":{"denied":[],"deniedRegex":""},"forbiddenLabels":{"denied":[],"deniedRegex":""}}` | Allows to set the forbidden metadata for the worker nodes that could be patched by a Tenant |
|
||||||
| manager.options.protectedNamespaceRegex | string | `""` | If specified, disallows creation of namespaces matching the passed regexp |
|
| manager.options.protectedNamespaceRegex | string | `""` | If specified, disallows creation of namespaces matching the passed regexp |
|
||||||
|
| manager.options.rbac | object | `{"administrationClusterRoles":["capsule-namespace-deleter"],"deleter":"capsule-namespace-deleter","promotionClusterRoles":["capsule-namespace-provisioner","capsule-namespace-deleter"],"provisioner":"capsule-namespace-provisioner"}` | Managed RBAC configuration for the controller |
|
||||||
|
| manager.options.rbac.administrationClusterRoles | list | `["capsule-namespace-deleter"]` | The ClusterRoles applied for Administrators |
|
||||||
|
| manager.options.rbac.deleter | string | `"capsule-namespace-deleter"` | Name for the ClusterRole required to grant Namespace Deletion permissions. |
|
||||||
|
| manager.options.rbac.promotionClusterRoles | list | `["capsule-namespace-provisioner","capsule-namespace-deleter"]` | The ClusterRoles applied for ServiceAccounts which had owner Promotion |
|
||||||
|
| manager.options.rbac.provisioner | string | `"capsule-namespace-provisioner"` | Name for the ClusterRole required to grant Namespace Provision permissions. |
|
||||||
|
| manager.options.userNames | list | `[]` | DEPRECATED: use users properties. Names of the users considered as Capsule users. |
|
||||||
|
| manager.options.users | list | `[{"kind":"Group","name":"projectcapsule.dev"}]` | Define entities which are considered part of the Capsule construct. Users not mentioned here will be ignored by Capsule |
|
||||||
|
| manager.options.workers | int | `1` | Workers (MaxConcurrentReconciles) is the maximum number of concurrent Reconciles which can be run (ALPHA). |
|
||||||
| manager.rbac.create | bool | `true` | Specifies whether RBAC resources should be created. |
|
| manager.rbac.create | bool | `true` | Specifies whether RBAC resources should be created. |
|
||||||
| manager.rbac.existingClusterRoles | list | `[]` | Specifies further cluster roles to be added to the Capsule manager service account. |
|
| manager.rbac.existingClusterRoles | list | `[]` | Specifies further cluster roles to be added to the Capsule manager service account. |
|
||||||
| manager.rbac.existingRoles | list | `[]` | Specifies further cluster roles to be added to the Capsule manager service account. |
|
| manager.rbac.existingRoles | list | `[]` | Specifies further cluster roles to be added to the Capsule manager service account. |
|
||||||
@@ -174,58 +145,163 @@ Here the values you can override:
|
|||||||
| manager.volumes | list | `[]` | Set the additional volumes needed for the Capsule manager container |
|
| manager.volumes | list | `[]` | Set the additional volumes needed for the Capsule manager container |
|
||||||
| manager.webhookPort | int | `9443` | Set an alternative to the default container port. Useful for use in some kubernetes clusters (such as GKE Private) with aggregator routing turned on, because pod ports have to be opened manually on the firewall side |
|
| manager.webhookPort | int | `9443` | Set an alternative to the default container port. Useful for use in some kubernetes clusters (such as GKE Private) with aggregator routing turned on, because pod ports have to be opened manually on the firewall side |
|
||||||
|
|
||||||
### ServiceMonitor Parameters
|
### Monitoring Parameters
|
||||||
|
|
||||||
| Key | Type | Default | Description |
|
| Key | Type | Default | Description |
|
||||||
|-----|------|---------|-------------|
|
|-----|------|---------|-------------|
|
||||||
| serviceMonitor.annotations | object | `{}` | Assign additional Annotations |
|
| monitoring.dashboards.annotations | object | `{}` | Annotations for dashboard configmaps |
|
||||||
| serviceMonitor.enabled | bool | `false` | Enable ServiceMonitor |
|
| monitoring.dashboards.enabled | bool | `false` | Enable Dashboards to be deployed |
|
||||||
| serviceMonitor.endpoint.interval | string | `"15s"` | Set the scrape interval for the endpoint of the serviceMonitor |
|
| monitoring.dashboards.labels | object | `{}` | Labels for dashboard configmaps |
|
||||||
| serviceMonitor.endpoint.metricRelabelings | list | `[]` | Set metricRelabelings for the endpoint of the serviceMonitor |
|
| monitoring.dashboards.namespace | string | `""` | Custom namespace for dashboard configmaps |
|
||||||
| serviceMonitor.endpoint.relabelings | list | `[]` | Set relabelings for the endpoint of the serviceMonitor |
|
| monitoring.dashboards.operator.allowCrossNamespaceImport | bool | `true` | Allow the Operator to match this resource with Grafanas outside the current namespace |
|
||||||
| serviceMonitor.endpoint.scrapeTimeout | string | `""` | Set the scrape timeout for the endpoint of the serviceMonitor |
|
| monitoring.dashboards.operator.enabled | bool | `false` | Enable Operator Resources (GrafanaDashboard) |
|
||||||
| serviceMonitor.labels | object | `{}` | Assign additional labels according to Prometheus' serviceMonitorSelector matching labels |
|
| monitoring.dashboards.operator.folder | string | `""` | folder assignment for dashboard |
|
||||||
| serviceMonitor.matchLabels | object | `{}` | Change matching labels |
|
| monitoring.dashboards.operator.instanceSelector | object | `{}` | Selects Grafana instances for import |
|
||||||
| serviceMonitor.namespace | string | `""` | Install the ServiceMonitor into a different Namespace, as the monitoring stack one (default: the release one) |
|
| monitoring.dashboards.operator.resyncPeriod | string | `"10m"` | How often the resource is synced, defaults to 10m0s if not set |
|
||||||
| serviceMonitor.targetLabels | list | `[]` | Set targetLabels for the serviceMonitor |
|
| monitoring.diagnostics.annotations | object | `{}` | Annotations for dashboard configmaps |
|
||||||
|
| monitoring.diagnostics.enabled | bool | `false` | Enable Diagnostic Dashboards to be deployed |
|
||||||
|
| monitoring.diagnostics.labels | object | `{}` | Labels for dashboard configmaps |
|
||||||
|
| monitoring.diagnostics.operator.allowCrossNamespaceImport | bool | `true` | Allow the Operator to match this resource with Grafanas outside the current namespace |
|
||||||
|
| monitoring.diagnostics.operator.enabled | bool | `false` | Enable Operator Resources (GrafanaDashboard) |
|
||||||
|
| monitoring.diagnostics.operator.folder | string | `""` | folder assignment for dashboard |
|
||||||
|
| monitoring.diagnostics.operator.instanceSelector | object | `{}` | Selects Grafana instances for import |
|
||||||
|
| monitoring.diagnostics.operator.resyncPeriod | string | `"10m"` | How often the resource is synced, defaults to 10m0s if not set |
|
||||||
|
| monitoring.serviceMonitor.annotations | object | `{}` | Assign additional Annotations |
|
||||||
|
| monitoring.serviceMonitor.enabled | bool | `false` | Enable ServiceMonitor |
|
||||||
|
| monitoring.serviceMonitor.endpoint.interval | string | `"15s"` | Set the scrape interval for the endpoint of the serviceMonitor |
|
||||||
|
| monitoring.serviceMonitor.endpoint.metricRelabelings | list | `[]` | Set metricRelabelings for the endpoint of the serviceMonitor |
|
||||||
|
| monitoring.serviceMonitor.endpoint.relabelings | list | `[]` | Set relabelings for the endpoint of the serviceMonitor |
|
||||||
|
| monitoring.serviceMonitor.endpoint.scrapeTimeout | string | `""` | Set the scrape timeout for the endpoint of the serviceMonitor |
|
||||||
|
| monitoring.serviceMonitor.labels | object | `{}` | Assign additional labels according to Prometheus' serviceMonitorSelector matching labels |
|
||||||
|
| monitoring.serviceMonitor.matchLabels | object | `{}` | Change matching labels |
|
||||||
|
| monitoring.serviceMonitor.namespace | string | `""` | Install the ServiceMonitor into a different Namespace, as the monitoring stack one (default: the release one) |
|
||||||
|
| monitoring.serviceMonitor.targetLabels | list | `[]` | Set targetLabels for the serviceMonitor |
|
||||||
|
|
||||||
### Webhooks Parameters
|
### Admission Webhook Parameters
|
||||||
|
|
||||||
| Key | Type | Default | Description |
|
| Key | Type | Default | Description |
|
||||||
|-----|------|---------|-------------|
|
|-----|------|---------|-------------|
|
||||||
|
| webhooks.annotations | object | `{}` | Additional Annotations for all webhooks |
|
||||||
| webhooks.exclusive | bool | `false` | When `crds.exclusive` is `true` the webhooks will be installed |
|
| webhooks.exclusive | bool | `false` | When `crds.exclusive` is `true` the webhooks will be installed |
|
||||||
| webhooks.hooks.cordoning.failurePolicy | string | `"Fail"` | |
|
| webhooks.hooks.config.enabled | bool | `true` | Enable the Hook |
|
||||||
| webhooks.hooks.cordoning.namespaceSelector.matchExpressions[0].key | string | `"capsule.clastix.io/tenant"` | |
|
| webhooks.hooks.config.failurePolicy | string | `"Ignore"` | [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) |
|
||||||
| webhooks.hooks.cordoning.namespaceSelector.matchExpressions[0].operator | string | `"Exists"` | |
|
| webhooks.hooks.config.matchConditions | list | `[]` | [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
| webhooks.hooks.defaults.ingress.failurePolicy | string | `"Fail"` | |
|
| webhooks.hooks.config.matchPolicy | string | `"Exact"` | [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
| webhooks.hooks.defaults.ingress.namespaceSelector.matchExpressions[0].key | string | `"capsule.clastix.io/tenant"` | |
|
| webhooks.hooks.config.namespaceSelector | object | `{}` | [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) |
|
||||||
| webhooks.hooks.defaults.ingress.namespaceSelector.matchExpressions[0].operator | string | `"Exists"` | |
|
| webhooks.hooks.config.objectSelector | object | `{}` | [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector) |
|
||||||
| webhooks.hooks.defaults.pods.failurePolicy | string | `"Fail"` | |
|
| webhooks.hooks.config.reinvocationPolicy | string | `"Never"` | [ReinvocationPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#reinvocation-policy) |
|
||||||
| webhooks.hooks.defaults.pods.namespaceSelector.matchExpressions[0].key | string | `"capsule.clastix.io/tenant"` | |
|
| webhooks.hooks.cordoning.enabled | bool | `true` | Enable the Hook |
|
||||||
| webhooks.hooks.defaults.pods.namespaceSelector.matchExpressions[0].operator | string | `"Exists"` | |
|
| webhooks.hooks.cordoning.failurePolicy | string | `"Fail"` | [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) |
|
||||||
| webhooks.hooks.defaults.pvc.failurePolicy | string | `"Fail"` | |
|
| webhooks.hooks.cordoning.matchConditions | list | `[{"expression":"!has(request.subResource) || request.subResource == \"\"","name":"ignore-subresources"},{"expression":"request.resource.resource != \"events\"","name":"ignore-events"}]` | [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
| webhooks.hooks.defaults.pvc.namespaceSelector.matchExpressions[0].key | string | `"capsule.clastix.io/tenant"` | |
|
| webhooks.hooks.cordoning.matchPolicy | string | `"Equivalent"` | [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
| webhooks.hooks.defaults.pvc.namespaceSelector.matchExpressions[0].operator | string | `"Exists"` | |
|
| webhooks.hooks.cordoning.namespaceSelector | object | `{"matchExpressions":[{"key":"capsule.clastix.io/tenant","operator":"Exists"},{"key":"projectcapsule.dev/cordoned","operator":"In","values":["true"]}]}` | [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) |
|
||||||
| webhooks.hooks.ingresses.failurePolicy | string | `"Fail"` | |
|
| webhooks.hooks.cordoning.objectSelector | object | `{}` | [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector) |
|
||||||
| webhooks.hooks.ingresses.namespaceSelector.matchExpressions[0].key | string | `"capsule.clastix.io/tenant"` | |
|
| webhooks.hooks.cordoning.rules | list | `[{"apiGroups":["*"],"apiVersions":["*"],"operations":["CREATE","UPDATE","DELETE"],"resources":["*"],"scope":"Namespaced"}]` | [Rules](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-rules) |
|
||||||
| webhooks.hooks.ingresses.namespaceSelector.matchExpressions[0].operator | string | `"Exists"` | |
|
| webhooks.hooks.customresources.enabled | bool | `true` | Enable the Hook |
|
||||||
| webhooks.hooks.namespaceOwnerReference.failurePolicy | string | `"Fail"` | |
|
| webhooks.hooks.customresources.failurePolicy | string | `"Fail"` | [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) |
|
||||||
| webhooks.hooks.namespaces.failurePolicy | string | `"Fail"` | |
|
| webhooks.hooks.customresources.matchConditions | list | `[{"expression":"!has(request.subResource) || request.subResource == \"\"","name":"ignore-subresources"},{"expression":"request.resource.resource != \"events\"","name":"ignore-events"}]` | [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
| webhooks.hooks.networkpolicies.failurePolicy | string | `"Fail"` | |
|
| webhooks.hooks.customresources.matchPolicy | string | `"Equivalent"` | [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
| webhooks.hooks.networkpolicies.namespaceSelector.matchExpressions[0].key | string | `"capsule.clastix.io/tenant"` | |
|
| webhooks.hooks.customresources.namespaceSelector | object | `{"matchExpressions":[{"key":"capsule.clastix.io/tenant","operator":"Exists"},{"key":"projectcapsule.dev/custom-resources","operator":"Exists"}]}` | [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) |
|
||||||
| webhooks.hooks.networkpolicies.namespaceSelector.matchExpressions[0].operator | string | `"Exists"` | |
|
| webhooks.hooks.customresources.objectSelector | object | `{}` | [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector) |
|
||||||
| webhooks.hooks.nodes.failurePolicy | string | `"Fail"` | |
|
| webhooks.hooks.defaults.ingress | object | `{}` | Deprecated, use webhooks.hooks.ingresses instead |
|
||||||
| webhooks.hooks.persistentvolumeclaims.failurePolicy | string | `"Fail"` | |
|
| webhooks.hooks.defaults.pods | object | `{}` | Deprecated, use webhooks.hooks.pods instead |
|
||||||
| webhooks.hooks.persistentvolumeclaims.namespaceSelector.matchExpressions[0].key | string | `"capsule.clastix.io/tenant"` | |
|
| webhooks.hooks.defaults.pvc | object | `{}` | Deprecated, use webhooks.hooks.persistentvolumeclaims instead |
|
||||||
| webhooks.hooks.persistentvolumeclaims.namespaceSelector.matchExpressions[0].operator | string | `"Exists"` | |
|
| webhooks.hooks.devices.enabled | bool | `true` | Enable the Hook |
|
||||||
| webhooks.hooks.pods.failurePolicy | string | `"Fail"` | |
|
| webhooks.hooks.devices.failurePolicy | string | `"Fail"` | [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) |
|
||||||
| webhooks.hooks.pods.namespaceSelector.matchExpressions[0].key | string | `"capsule.clastix.io/tenant"` | |
|
| webhooks.hooks.devices.matchConditions | list | `[]` | [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
| webhooks.hooks.pods.namespaceSelector.matchExpressions[0].operator | string | `"Exists"` | |
|
| webhooks.hooks.devices.matchPolicy | string | `"Equivalent"` | [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
| webhooks.hooks.services.failurePolicy | string | `"Fail"` | |
|
| webhooks.hooks.devices.namespaceSelector | object | `{"matchExpressions":[{"key":"capsule.clastix.io/tenant","operator":"Exists"}]}` | [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) |
|
||||||
| webhooks.hooks.services.namespaceSelector.matchExpressions[0].key | string | `"capsule.clastix.io/tenant"` | |
|
| webhooks.hooks.devices.objectSelector | object | `{}` | [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector) |
|
||||||
| webhooks.hooks.services.namespaceSelector.matchExpressions[0].operator | string | `"Exists"` | |
|
| webhooks.hooks.devices.reinvocationPolicy | string | `"Never"` | [ReinvocationPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#reinvocation-policy) |
|
||||||
| webhooks.hooks.tenantResourceObjects.failurePolicy | string | `"Fail"` | |
|
| webhooks.hooks.gateways.enabled | bool | `true` | Enable the Hook |
|
||||||
| webhooks.hooks.tenants.failurePolicy | string | `"Fail"` | |
|
| webhooks.hooks.gateways.failurePolicy | string | `"Fail"` | [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) |
|
||||||
|
| webhooks.hooks.gateways.matchConditions | list | `[]` | [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.gateways.matchPolicy | string | `"Equivalent"` | [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.gateways.namespaceSelector | object | `{"matchExpressions":[{"key":"capsule.clastix.io/tenant","operator":"Exists"}]}` | [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) |
|
||||||
|
| webhooks.hooks.gateways.objectSelector | object | `{}` | [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector) |
|
||||||
|
| webhooks.hooks.ingresses.enabled | bool | `true` | Enable the Hook |
|
||||||
|
| webhooks.hooks.ingresses.failurePolicy | string | `"Fail"` | [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) |
|
||||||
|
| webhooks.hooks.ingresses.matchConditions | list | `[]` | [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.ingresses.matchPolicy | string | `"Equivalent"` | [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.ingresses.namespaceSelector | object | `{"matchExpressions":[{"key":"capsule.clastix.io/tenant","operator":"Exists"}]}` | [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) |
|
||||||
|
| webhooks.hooks.ingresses.objectSelector | object | `{}` | [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector) |
|
||||||
|
| webhooks.hooks.ingresses.reinvocationPolicy | string | `"Never"` | [ReinvocationPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#reinvocation-policy) |
|
||||||
|
| webhooks.hooks.managed.enabled | bool | `true` | Enable the Hook |
|
||||||
|
| webhooks.hooks.managed.failurePolicy | string | `"Fail"` | [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) |
|
||||||
|
| webhooks.hooks.managed.matchConditions | list | `[]` | [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.managed.matchPolicy | string | `"Exact"` | [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.managed.namespaceSelector | object | `{"matchExpressions":[{"key":"capsule.clastix.io/tenant","operator":"Exists"}]}` | [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) |
|
||||||
|
| webhooks.hooks.managed.objectSelector | object | `{"matchExpressions":[{"key":"projectcapsule.dev/managed-by","operator":"Exists"}]}` | [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector) |
|
||||||
|
| webhooks.hooks.managed.rules | list | `[{"apiGroups":["*"],"apiVersions":["*"],"operations":["CREATE","UPDATE","DELETE"],"resources":["*"],"scope":"*"}]` | [Rules](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-rules) |
|
||||||
|
| webhooks.hooks.namespaceOwnerReference | object | `{}` | Deprecated, use webhooks.hooks.namespaces instead |
|
||||||
|
| webhooks.hooks.namespaces.enabled | bool | `true` | Enable the Hook |
|
||||||
|
| webhooks.hooks.namespaces.failurePolicy | string | `"Fail"` | [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) |
|
||||||
|
| webhooks.hooks.namespaces.matchConditions | list | `[]` | [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.namespaces.matchPolicy | string | `"Equivalent"` | [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.namespaces.namespaceSelector | object | `{}` | [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) |
|
||||||
|
| webhooks.hooks.namespaces.objectSelector | object | `{}` | [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector) |
|
||||||
|
| webhooks.hooks.namespaces.reinvocationPolicy | string | `"Never"` | [ReinvocationPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#reinvocation-policy) |
|
||||||
|
| webhooks.hooks.nodes.enabled | bool | `false` | Enable the Hook |
|
||||||
|
| webhooks.hooks.nodes.failurePolicy | string | `"Fail"` | [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) |
|
||||||
|
| webhooks.hooks.nodes.matchConditions | list | `[]` | [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.nodes.matchPolicy | string | `"Exact"` | [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.nodes.namespaceSelector | object | `{}` | [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) |
|
||||||
|
| webhooks.hooks.nodes.objectSelector | object | `{}` | [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector) |
|
||||||
|
| webhooks.hooks.persistentvolumeclaims.enabled | bool | `true` | Enable the Hook |
|
||||||
|
| webhooks.hooks.persistentvolumeclaims.failurePolicy | string | `"Fail"` | [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) |
|
||||||
|
| webhooks.hooks.persistentvolumeclaims.matchConditions | list | `[]` | [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.persistentvolumeclaims.matchPolicy | string | `"Equivalent"` | [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.persistentvolumeclaims.namespaceSelector | object | `{"matchExpressions":[{"key":"capsule.clastix.io/tenant","operator":"Exists"}]}` | [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) |
|
||||||
|
| webhooks.hooks.persistentvolumeclaims.objectSelector | object | `{}` | [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector) |
|
||||||
|
| webhooks.hooks.persistentvolumeclaims.reinvocationPolicy | string | `"Never"` | [ReinvocationPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#reinvocation-policy) |
|
||||||
|
| webhooks.hooks.pods.enabled | bool | `true` | Enable the Hook |
|
||||||
|
| webhooks.hooks.pods.failurePolicy | string | `"Fail"` | [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) |
|
||||||
|
| webhooks.hooks.pods.matchConditions | list | `[]` | [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.pods.matchPolicy | string | `"Exact"` | [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.pods.namespaceSelector | object | `{"matchExpressions":[{"key":"capsule.clastix.io/tenant","operator":"Exists"}]}` | [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) |
|
||||||
|
| webhooks.hooks.pods.objectSelector | object | `{}` | [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector) |
|
||||||
|
| webhooks.hooks.pods.reinvocationPolicy | string | `"Never"` | [ReinvocationPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#reinvocation-policy) |
|
||||||
|
| webhooks.hooks.resourcepools.claims.enabled | bool | `true` | Enable the Hook |
|
||||||
|
| webhooks.hooks.resourcepools.claims.failurePolicy | string | `"Fail"` | [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) |
|
||||||
|
| webhooks.hooks.resourcepools.claims.matchConditions | list | `[]` | [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.resourcepools.claims.matchPolicy | string | `"Equivalent"` | [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.resourcepools.claims.namespaceSelector | object | `{}` | [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) |
|
||||||
|
| webhooks.hooks.resourcepools.claims.objectSelector | object | `{}` | [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector) |
|
||||||
|
| webhooks.hooks.resourcepools.pools.enabled | bool | `true` | Enable the Hook |
|
||||||
|
| webhooks.hooks.resourcepools.pools.failurePolicy | string | `"Fail"` | [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) |
|
||||||
|
| webhooks.hooks.resourcepools.pools.matchConditions | list | `[]` | [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.resourcepools.pools.matchPolicy | string | `"Equivalent"` | [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.resourcepools.pools.namespaceSelector | object | `{}` | [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) |
|
||||||
|
| webhooks.hooks.resourcepools.pools.objectSelector | object | `{}` | [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector) |
|
||||||
|
| webhooks.hooks.serviceaccounts.enabled | bool | `true` | Enable the Hook |
|
||||||
|
| webhooks.hooks.serviceaccounts.failurePolicy | string | `"Fail"` | [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) |
|
||||||
|
| webhooks.hooks.serviceaccounts.matchConditions | list | `[]` | [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.serviceaccounts.matchPolicy | string | `"Exact"` | [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.serviceaccounts.namespaceSelector | object | `{"matchExpressions":[{"key":"capsule.clastix.io/tenant","operator":"Exists"}]}` | [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) |
|
||||||
|
| webhooks.hooks.serviceaccounts.objectSelector | object | `{}` | [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector) |
|
||||||
|
| webhooks.hooks.services.enabled | bool | `true` | Enable the Hook |
|
||||||
|
| webhooks.hooks.services.failurePolicy | string | `"Fail"` | [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) |
|
||||||
|
| webhooks.hooks.services.matchConditions | list | `[]` | [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.services.matchPolicy | string | `"Exact"` | [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.services.namespaceSelector | object | `{"matchExpressions":[{"key":"capsule.clastix.io/tenant","operator":"Exists"}]}` | [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) |
|
||||||
|
| webhooks.hooks.services.objectSelector | object | `{}` | [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector) |
|
||||||
|
| webhooks.hooks.tenantLabel.enabled | bool | `true` | Enable the Hook |
|
||||||
|
| webhooks.hooks.tenantLabel.failurePolicy | string | `"Fail"` | [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) |
|
||||||
|
| webhooks.hooks.tenantLabel.matchConditions | list | `[{"expression":"!has(request.subResource) || request.subResource == \"\"","name":"ignore-subresources"},{"expression":"request.resource.resource != \"events\"","name":"ignore-events"}]` | [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.tenantLabel.matchPolicy | string | `"Equivalent"` | [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.tenantLabel.namespaceSelector | object | `{"matchExpressions":[{"key":"capsule.clastix.io/tenant","operator":"Exists"}]}` | [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) |
|
||||||
|
| webhooks.hooks.tenantLabel.objectSelector | object | `{}` | [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector) |
|
||||||
|
| webhooks.hooks.tenantLabel.reinvocationPolicy | string | `"Never"` | [ReinvocationPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#reinvocation-policy) |
|
||||||
|
| webhooks.hooks.tenantLabel.rules | list | `[{"apiGroups":["*"],"apiVersions":["*"],"operations":["CREATE","UPDATE"],"resources":["*"],"scope":"Namespaced"}]` | [Rules](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-rules) |
|
||||||
|
| webhooks.hooks.tenantResourceObjects | object | `{}` | Deprecated, use webhooks.hooks.managed instead |
|
||||||
|
| webhooks.hooks.tenants.enabled | bool | `true` | Enable the Hook |
|
||||||
|
| webhooks.hooks.tenants.failurePolicy | string | `"Fail"` | [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) |
|
||||||
|
| webhooks.hooks.tenants.matchConditions | list | `[]` | [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.tenants.matchPolicy | string | `"Exact"` | [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy) |
|
||||||
|
| webhooks.hooks.tenants.namespaceSelector | object | `{}` | [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector) |
|
||||||
|
| webhooks.hooks.tenants.objectSelector | object | `{}` | [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector) |
|
||||||
|
| webhooks.hooks.tenants.reinvocationPolicy | string | `"Never"` | [ReinvocationPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#reinvocation-policy) |
|
||||||
|
| webhooks.labels | object | `{}` | Additional Labels for all webhooks |
|
||||||
| webhooks.mutatingWebhooksTimeoutSeconds | int | `30` | Timeout in seconds for mutating webhooks |
|
| webhooks.mutatingWebhooksTimeoutSeconds | int | `30` | Timeout in seconds for mutating webhooks |
|
||||||
| webhooks.service.caBundle | string | `""` | CABundle for the webhook service |
|
| webhooks.service.caBundle | string | `""` | CABundle for the webhook service |
|
||||||
| webhooks.service.name | string | `""` | Custom service name for the webhook service |
|
| webhooks.service.name | string | `""` | Custom service name for the webhook service |
|
||||||
@@ -234,30 +310,6 @@ Here the values you can override:
|
|||||||
| webhooks.service.url | string | `""` | The URL where the capsule webhook services are running (Overwrites cluster scoped service definition) |
|
| webhooks.service.url | string | `""` | The URL where the capsule webhook services are running (Overwrites cluster scoped service definition) |
|
||||||
| webhooks.validatingWebhooksTimeoutSeconds | int | `30` | Timeout in seconds for validating webhooks |
|
| webhooks.validatingWebhooksTimeoutSeconds | int | `30` | Timeout in seconds for validating webhooks |
|
||||||
|
|
||||||
## Created resources
|
|
||||||
|
|
||||||
This Helm Chart creates the following Kubernetes resources in the release namespace:
|
|
||||||
|
|
||||||
* Capsule Namespace
|
|
||||||
* Capsule Operator Deployment
|
|
||||||
* Capsule Service
|
|
||||||
* CA Secret
|
|
||||||
* Certificate Secret
|
|
||||||
* Tenant Custom Resource Definition
|
|
||||||
* CapsuleConfiguration Custom Resource Definition
|
|
||||||
* MutatingWebHookConfiguration
|
|
||||||
* ValidatingWebHookConfiguration
|
|
||||||
* RBAC Cluster Roles
|
|
||||||
* Metrics Service
|
|
||||||
|
|
||||||
And optionally, depending on the values set:
|
|
||||||
|
|
||||||
* Capsule ServiceAccount
|
|
||||||
* Capsule Service Monitor
|
|
||||||
* PodSecurityPolicy
|
|
||||||
* RBAC ClusterRole and RoleBinding for pod security policy
|
|
||||||
* RBAC Role and Rolebinding for metrics scrape
|
|
||||||
|
|
||||||
## Notes on installing Custom Resource Definitions with Helm3
|
## Notes on installing Custom Resource Definitions with Helm3
|
||||||
|
|
||||||
Capsule, as many other add-ons, defines its own set of Custom Resource Definitions (CRDs). Helm3 removed the old CRDs installation method for a more simple methodology. In the Helm Chart, there is now a special directory called `crds` to hold the CRDs. These CRDs are not templated, but will be installed by default when running a `helm install` for the chart. If the CRDs already exist (for example, you already executed `helm install`), it will be skipped with a warning. When you wish to skip the CRDs installation, and do not see the warning, you can pass the `--skip-crds` flag to the `helm install` command.
|
Capsule, as many other add-ons, defines its own set of Custom Resource Definitions (CRDs). Helm3 removed the old CRDs installation method for a more simple methodology. In the Helm Chart, there is now a special directory called `crds` to hold the CRDs. These CRDs are not templated, but will be installed by default when running a `helm install` for the chart. If the CRDs already exist (for example, you already executed `helm install`), it will be skipped with a warning. When you wish to skip the CRDs installation, and do not see the warning, you can pass the `--skip-crds` flag to the `helm install` command.
|
||||||
|
|||||||
@@ -1,20 +1,8 @@
|
|||||||
# Deploying the Capsule Operator
|
# Deploying the Capsule Operator
|
||||||
|
|
||||||
Use the Capsule Operator for easily implementing, managing, and maintaining multitenancy and access control in Kubernetes.
|
Use the Capsule Operator for easily implementing, managing, and maintaining multitenancy and access control in Kubernetes. Please read our installation guide:
|
||||||
|
|
||||||
## Requirements
|
* [https://projectcapsule.dev/docs/operating/setup/installation/](https://projectcapsule.dev/docs/operating/setup/installation/)
|
||||||
|
|
||||||
* [Helm 3](https://github.com/helm/helm/releases) is required when installing the Capsule Operator chart. Follow Helm’s official [steps](https://helm.sh/docs/intro/install/) for installing helm on your particular operating system.
|
|
||||||
|
|
||||||
* A Kubernetes cluster 1.16+ with following [Admission Controllers](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/) enabled:
|
|
||||||
|
|
||||||
* PodNodeSelector
|
|
||||||
* LimitRanger
|
|
||||||
* ResourceQuota
|
|
||||||
* MutatingAdmissionWebhook
|
|
||||||
* ValidatingAdmissionWebhook
|
|
||||||
|
|
||||||
* A [`kubeconfig`](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/) file accessing the Kubernetes cluster with cluster admin permissions.
|
|
||||||
|
|
||||||
## Major Changes
|
## Major Changes
|
||||||
|
|
||||||
@@ -33,59 +21,7 @@ The following Values have changed key or Value:
|
|||||||
* `mutatingWebhooksTimeoutSeconds` has moved to `webhooks.mutatingWebhooksTimeoutSeconds`
|
* `mutatingWebhooksTimeoutSeconds` has moved to `webhooks.mutatingWebhooksTimeoutSeconds`
|
||||||
* `validatingWebhooksTimeoutSeconds` has moved to `webhooks.validatingWebhooksTimeoutSeconds`
|
* `validatingWebhooksTimeoutSeconds` has moved to `webhooks.validatingWebhooksTimeoutSeconds`
|
||||||
|
|
||||||
|
## Values
|
||||||
## Installation
|
|
||||||
|
|
||||||
**When using OCI we recommend our dedicated [OCI Repository](https://artifacthub.io/packages/helm/capsule/capsule) for this chart**
|
|
||||||
|
|
||||||
The Capsule Operator requires it's CRDs to be installed before the operator itself. Since the Helm CRD lifecycle has limitations, we recommend to install the CRDs separately. Our chart supports the installation of crds via a dedicated Release.
|
|
||||||
The Capsule Operator Chart can be used to instantly deploy the Capsule Operator on your Kubernetes cluster.
|
|
||||||
|
|
||||||
1. Add this repository:
|
|
||||||
|
|
||||||
$ helm repo add projectcapsule https://projectcapsule.github.io/charts
|
|
||||||
|
|
||||||
2. Install Capsule:
|
|
||||||
|
|
||||||
$ helm install capsule projectcapsule/capsule --version 0.7.0 -n capsule-system --create-namespace
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
$ helm install capsule oci://ghcr.io/projectcapsule/charts/capsule --version 0.7.0 -n capsule-system --create-namespace
|
|
||||||
|
|
||||||
3. Show the status:
|
|
||||||
|
|
||||||
$ helm status capsule -n capsule-system
|
|
||||||
|
|
||||||
4. Upgrade the Chart
|
|
||||||
|
|
||||||
$ helm upgrade capsule projectcapsule/capsule -n capsule-system
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
$ helm upgrade capsule oci://ghcr.io/projectcapsule/charts/capsule --version 0.4.7
|
|
||||||
|
|
||||||
5. Uninstall the Chart
|
|
||||||
|
|
||||||
$ helm uninstall capsule -n capsule-system
|
|
||||||
|
|
||||||
## Customize the installation
|
|
||||||
|
|
||||||
There are two methods for specifying overrides of values during chart installation: `--values` and `--set`.
|
|
||||||
|
|
||||||
The `--values` option is the preferred method because it allows you to keep your overrides in a YAML file, rather than specifying them all on the command line. Create a copy of the YAML file `values.yaml` and add your overrides to it.
|
|
||||||
|
|
||||||
Specify your overrides file when you install the chart:
|
|
||||||
|
|
||||||
$ helm install capsule capsule-helm-chart --values myvalues.yaml -n capsule-system
|
|
||||||
|
|
||||||
The values in your overrides file `myvalues.yaml` will override their counterparts in the chart's values.yaml file. Any values in `values.yaml` that weren’t overridden will keep their defaults.
|
|
||||||
|
|
||||||
If you only need to make minor customizations, you can specify them on the command line by using the `--set` option. For example:
|
|
||||||
|
|
||||||
$ helm install capsule capsule-helm-chart --set manager.options.forceTenantPrefix=false -n capsule-system
|
|
||||||
|
|
||||||
Here the values you can override:
|
|
||||||
|
|
||||||
### CustomResourceDefinition Lifecycle
|
### CustomResourceDefinition Lifecycle
|
||||||
|
|
||||||
@@ -112,7 +48,7 @@ Here the values you can override:
|
|||||||
| Key | Type | Default | Description |
|
| Key | Type | Default | Description |
|
||||||
|-----|------|---------|-------------|
|
|-----|------|---------|-------------|
|
||||||
{{- range .Values }}
|
{{- range .Values }}
|
||||||
{{- if not (or (hasPrefix "global" .Key) (hasPrefix "manager" .Key) (hasPrefix "crds" .Key) (hasPrefix "serviceMonitor" .Key) (hasPrefix "webhook" .Key) (hasPrefix "capsule-proxy" .Key) ) }}
|
{{- if not (or (hasPrefix "global" .Key) (hasPrefix "manager" .Key) (hasPrefix "crds" .Key) (hasPrefix "monitoring" .Key) (hasPrefix "webhook" .Key) (hasPrefix "capsule-proxy" .Key) ) }}
|
||||||
| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} |
|
| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} |
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
@@ -127,17 +63,17 @@ Here the values you can override:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
### ServiceMonitor Parameters
|
### Monitoring Parameters
|
||||||
|
|
||||||
| Key | Type | Default | Description |
|
| Key | Type | Default | Description |
|
||||||
|-----|------|---------|-------------|
|
|-----|------|---------|-------------|
|
||||||
{{- range .Values }}
|
{{- range .Values }}
|
||||||
{{- if hasPrefix "serviceMonitor" .Key }}
|
{{- if hasPrefix "monitoring" .Key }}
|
||||||
| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} |
|
| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} |
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
### Webhooks Parameters
|
### Admission Webhook Parameters
|
||||||
|
|
||||||
| Key | Type | Default | Description |
|
| Key | Type | Default | Description |
|
||||||
|-----|------|---------|-------------|
|
|-----|------|---------|-------------|
|
||||||
@@ -147,30 +83,6 @@ Here the values you can override:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
## Created resources
|
|
||||||
|
|
||||||
This Helm Chart creates the following Kubernetes resources in the release namespace:
|
|
||||||
|
|
||||||
* Capsule Namespace
|
|
||||||
* Capsule Operator Deployment
|
|
||||||
* Capsule Service
|
|
||||||
* CA Secret
|
|
||||||
* Certificate Secret
|
|
||||||
* Tenant Custom Resource Definition
|
|
||||||
* CapsuleConfiguration Custom Resource Definition
|
|
||||||
* MutatingWebHookConfiguration
|
|
||||||
* ValidatingWebHookConfiguration
|
|
||||||
* RBAC Cluster Roles
|
|
||||||
* Metrics Service
|
|
||||||
|
|
||||||
And optionally, depending on the values set:
|
|
||||||
|
|
||||||
* Capsule ServiceAccount
|
|
||||||
* Capsule Service Monitor
|
|
||||||
* PodSecurityPolicy
|
|
||||||
* RBAC ClusterRole and RoleBinding for pod security policy
|
|
||||||
* RBAC Role and Rolebinding for metrics scrape
|
|
||||||
|
|
||||||
## Notes on installing Custom Resource Definitions with Helm3
|
## Notes on installing Custom Resource Definitions with Helm3
|
||||||
|
|
||||||
Capsule, as many other add-ons, defines its own set of Custom Resource Definitions (CRDs). Helm3 removed the old CRDs installation method for a more simple methodology. In the Helm Chart, there is now a special directory called `crds` to hold the CRDs. These CRDs are not templated, but will be installed by default when running a `helm install` for the chart. If the CRDs already exist (for example, you already executed `helm install`), it will be skipped with a warning. When you wish to skip the CRDs installation, and do not see the warning, you can pass the `--skip-crds` flag to the `helm install` command.
|
Capsule, as many other add-ons, defines its own set of Custom Resource Definitions (CRDs). Helm3 removed the old CRDs installation method for a more simple methodology. In the Helm Chart, there is now a special directory called `crds` to hold the CRDs. These CRDs are not templated, but will be installed by default when running a `helm install` for the chart. If the CRDs already exist (for example, you already executed `helm install`), it will be skipped with a warning. When you wish to skip the CRDs installation, and do not see the warning, you can pass the `--skip-crds` flag to the `helm install` command.
|
||||||
|
|||||||
8
charts/capsule/ci/extra-values.yaml
Normal file
8
charts/capsule/ci/extra-values.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# -- Array of additional resources to be created alongside Capsule helm chart
|
||||||
|
extraManifests:
|
||||||
|
- apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: random-config
|
||||||
|
data:
|
||||||
|
random-value: "{{ randAlphaNum 16 }}"
|
||||||
4
charts/capsule/ci/ha-values.yaml
Normal file
4
charts/capsule/ci/ha-values.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
replicaCount: 2
|
||||||
|
manager:
|
||||||
|
extraArgs:
|
||||||
|
- "--enable-leader-election=true"
|
||||||
9
charts/capsule/ci/monitoring-values.yaml
Normal file
9
charts/capsule/ci/monitoring-values.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
monitoring:
|
||||||
|
dashboards:
|
||||||
|
enabled: true
|
||||||
|
annotations:
|
||||||
|
k8s-sidecar-target-directory: /tmp/dashboards/Capsule
|
||||||
|
labels:
|
||||||
|
grafana_dashboard: "1"
|
||||||
|
operator:
|
||||||
|
enabled: true
|
||||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.17.2
|
controller-gen.kubebuilder.io/version: v0.20.0
|
||||||
name: capsuleconfigurations.capsule.clastix.io
|
name: capsuleconfigurations.capsule.clastix.io
|
||||||
spec:
|
spec:
|
||||||
group: capsule.clastix.io
|
group: capsule.clastix.io
|
||||||
@@ -40,8 +40,233 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
description: CapsuleConfigurationSpec defines the Capsule configuration.
|
description: CapsuleConfigurationSpec defines the Capsule configuration.
|
||||||
properties:
|
properties:
|
||||||
|
administrators:
|
||||||
|
description: |-
|
||||||
|
Define entities which can act as Administrators in the capsule construct
|
||||||
|
These entities are automatically owners for all existing tenants. Meaning they can add namespaces to any tenant. However they must be specific by using the capsule label
|
||||||
|
for interacting with namespaces. Because if that label is not defined, it's assumed that namespace interaction was not targeted towards a tenant and will therefor
|
||||||
|
be ignored by capsule.
|
||||||
|
items:
|
||||||
|
properties:
|
||||||
|
kind:
|
||||||
|
description: Kind of entity. Possible values are "User", "Group",
|
||||||
|
and "ServiceAccount"
|
||||||
|
enum:
|
||||||
|
- User
|
||||||
|
- Group
|
||||||
|
- ServiceAccount
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: Name of the entity.
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- kind
|
||||||
|
- name
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
admission:
|
||||||
|
description: Configuration for dynamic Validating and Mutating Admission
|
||||||
|
webhooks managed by Capsule.
|
||||||
|
properties:
|
||||||
|
mutating:
|
||||||
|
description: Configure dynamic Mutating Admission for Capsule
|
||||||
|
properties:
|
||||||
|
annotations:
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
description: Annotations added to the Admission Webhook
|
||||||
|
type: object
|
||||||
|
client:
|
||||||
|
description: From the upstram struct
|
||||||
|
properties:
|
||||||
|
caBundle:
|
||||||
|
description: |-
|
||||||
|
`caBundle` is a PEM encoded CA bundle which will be used to validate the webhook's server certificate.
|
||||||
|
If unspecified, system trust roots on the apiserver are used.
|
||||||
|
format: byte
|
||||||
|
type: string
|
||||||
|
service:
|
||||||
|
description: |-
|
||||||
|
`service` is a reference to the service for this webhook. Either
|
||||||
|
`service` or `url` must be specified.
|
||||||
|
|
||||||
|
If the webhook is running within the cluster, then you should use `service`.
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: |-
|
||||||
|
`name` is the name of the service.
|
||||||
|
Required
|
||||||
|
type: string
|
||||||
|
namespace:
|
||||||
|
description: |-
|
||||||
|
`namespace` is the namespace of the service.
|
||||||
|
Required
|
||||||
|
type: string
|
||||||
|
path:
|
||||||
|
description: |-
|
||||||
|
`path` is an optional URL path which will be sent in any request to
|
||||||
|
this service.
|
||||||
|
type: string
|
||||||
|
port:
|
||||||
|
description: |-
|
||||||
|
If specified, the port on the service that hosting webhook.
|
||||||
|
Default to 443 for backward compatibility.
|
||||||
|
`port` should be a valid port number (1-65535, inclusive).
|
||||||
|
format: int32
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- namespace
|
||||||
|
type: object
|
||||||
|
url:
|
||||||
|
description: |-
|
||||||
|
`url` gives the location of the webhook, in standard URL form
|
||||||
|
(`scheme://host:port/path`). Exactly one of `url` or `service`
|
||||||
|
must be specified.
|
||||||
|
|
||||||
|
The `host` should not refer to a service running in the cluster; use
|
||||||
|
the `service` field instead. The host might be resolved via external
|
||||||
|
DNS in some apiservers (e.g., `kube-apiserver` cannot resolve
|
||||||
|
in-cluster DNS as that would be a layering violation). `host` may
|
||||||
|
also be an IP address.
|
||||||
|
|
||||||
|
Please note that using `localhost` or `127.0.0.1` as a `host` is
|
||||||
|
risky unless you take great care to run this webhook on all hosts
|
||||||
|
which run an apiserver which might need to make calls to this
|
||||||
|
webhook. Such installs are likely to be non-portable, i.e., not easy
|
||||||
|
to turn up in a new cluster.
|
||||||
|
|
||||||
|
The scheme must be "https"; the URL must begin with "https://".
|
||||||
|
|
||||||
|
A path is optional, and if present may be any string permissible in
|
||||||
|
a URL. You may use the path to pass an arbitrary string to the
|
||||||
|
webhook, for example, a cluster identifier.
|
||||||
|
|
||||||
|
Attempting to use a user or basic auth e.g. "user:password@" is not
|
||||||
|
allowed. Fragments ("#...") and query parameters ("?...") are not
|
||||||
|
allowed, either.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
labels:
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
description: Labels added to the Admission Webhook
|
||||||
|
type: object
|
||||||
|
name:
|
||||||
|
description: Name the Admission Webhook
|
||||||
|
maxLength: 63
|
||||||
|
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- client
|
||||||
|
type: object
|
||||||
|
validating:
|
||||||
|
description: Configure dynamic Validating Admission for Capsule
|
||||||
|
properties:
|
||||||
|
annotations:
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
description: Annotations added to the Admission Webhook
|
||||||
|
type: object
|
||||||
|
client:
|
||||||
|
description: From the upstram struct
|
||||||
|
properties:
|
||||||
|
caBundle:
|
||||||
|
description: |-
|
||||||
|
`caBundle` is a PEM encoded CA bundle which will be used to validate the webhook's server certificate.
|
||||||
|
If unspecified, system trust roots on the apiserver are used.
|
||||||
|
format: byte
|
||||||
|
type: string
|
||||||
|
service:
|
||||||
|
description: |-
|
||||||
|
`service` is a reference to the service for this webhook. Either
|
||||||
|
`service` or `url` must be specified.
|
||||||
|
|
||||||
|
If the webhook is running within the cluster, then you should use `service`.
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: |-
|
||||||
|
`name` is the name of the service.
|
||||||
|
Required
|
||||||
|
type: string
|
||||||
|
namespace:
|
||||||
|
description: |-
|
||||||
|
`namespace` is the namespace of the service.
|
||||||
|
Required
|
||||||
|
type: string
|
||||||
|
path:
|
||||||
|
description: |-
|
||||||
|
`path` is an optional URL path which will be sent in any request to
|
||||||
|
this service.
|
||||||
|
type: string
|
||||||
|
port:
|
||||||
|
description: |-
|
||||||
|
If specified, the port on the service that hosting webhook.
|
||||||
|
Default to 443 for backward compatibility.
|
||||||
|
`port` should be a valid port number (1-65535, inclusive).
|
||||||
|
format: int32
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- namespace
|
||||||
|
type: object
|
||||||
|
url:
|
||||||
|
description: |-
|
||||||
|
`url` gives the location of the webhook, in standard URL form
|
||||||
|
(`scheme://host:port/path`). Exactly one of `url` or `service`
|
||||||
|
must be specified.
|
||||||
|
|
||||||
|
The `host` should not refer to a service running in the cluster; use
|
||||||
|
the `service` field instead. The host might be resolved via external
|
||||||
|
DNS in some apiservers (e.g., `kube-apiserver` cannot resolve
|
||||||
|
in-cluster DNS as that would be a layering violation). `host` may
|
||||||
|
also be an IP address.
|
||||||
|
|
||||||
|
Please note that using `localhost` or `127.0.0.1` as a `host` is
|
||||||
|
risky unless you take great care to run this webhook on all hosts
|
||||||
|
which run an apiserver which might need to make calls to this
|
||||||
|
webhook. Such installs are likely to be non-portable, i.e., not easy
|
||||||
|
to turn up in a new cluster.
|
||||||
|
|
||||||
|
The scheme must be "https"; the URL must begin with "https://".
|
||||||
|
|
||||||
|
A path is optional, and if present may be any string permissible in
|
||||||
|
a URL. You may use the path to pass an arbitrary string to the
|
||||||
|
webhook, for example, a cluster identifier.
|
||||||
|
|
||||||
|
Attempting to use a user or basic auth e.g. "user:password@" is not
|
||||||
|
allowed. Fragments ("#...") and query parameters ("?...") are not
|
||||||
|
allowed, either.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
labels:
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
description: Labels added to the Admission Webhook
|
||||||
|
type: object
|
||||||
|
name:
|
||||||
|
description: Name the Admission Webhook
|
||||||
|
maxLength: 63
|
||||||
|
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- client
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
allowServiceAccountPromotion:
|
||||||
|
default: false
|
||||||
|
description: |-
|
||||||
|
ServiceAccounts within tenant namespaces can be promoted to owners of the given tenant
|
||||||
|
this can be achieved by labeling the serviceaccount and then they are considered owners. This can only be done by other owners of the tenant.
|
||||||
|
However ServiceAccounts which have been promoted to owner can not promote further serviceAccounts.
|
||||||
|
type: boolean
|
||||||
|
cacheInvalidation:
|
||||||
|
default: 24h
|
||||||
|
description: Define the period of time upon a cache invalidation is
|
||||||
|
executed for all caches.
|
||||||
|
type: string
|
||||||
enableTLSReconciler:
|
enableTLSReconciler:
|
||||||
default: true
|
default: false
|
||||||
description: |-
|
description: |-
|
||||||
Toggles the TLS reconciler, the controller that is able to generate CA and certificates for the webhooks
|
Toggles the TLS reconciler, the controller that is able to generate CA and certificates for the webhooks
|
||||||
when not using an already provided CA and certificate, or when these are managed externally with Vault, or cert-manager.
|
when not using an already provided CA and certificate, or when these are managed externally with Vault, or cert-manager.
|
||||||
@@ -52,6 +277,13 @@ spec:
|
|||||||
Enforces the Tenant owner, during Namespace creation, to name it using the selected Tenant name as prefix,
|
Enforces the Tenant owner, during Namespace creation, to name it using the selected Tenant name as prefix,
|
||||||
separated by a dash. This is useful to avoid Namespace name collision in a public CaaS environment.
|
separated by a dash. This is useful to avoid Namespace name collision in a public CaaS environment.
|
||||||
type: boolean
|
type: boolean
|
||||||
|
ignoreUserWithGroups:
|
||||||
|
description: |-
|
||||||
|
Define groups which when found in the request of a user will be ignored by the Capsule
|
||||||
|
this might be useful if you have one group where all the users are in, but you want to separate administrators from normal users with additional groups.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
nodeMetadata:
|
nodeMetadata:
|
||||||
description: |-
|
description: |-
|
||||||
Allows to set the forbidden metadata for the worker nodes that could be patched by a Tenant.
|
Allows to set the forbidden metadata for the worker nodes that could be patched by a Tenant.
|
||||||
@@ -79,9 +311,6 @@ spec:
|
|||||||
deniedRegex:
|
deniedRegex:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
required:
|
|
||||||
- forbiddenAnnotations
|
|
||||||
- forbiddenLabels
|
|
||||||
type: object
|
type: object
|
||||||
overrides:
|
overrides:
|
||||||
default:
|
default:
|
||||||
@@ -117,16 +346,114 @@ spec:
|
|||||||
description: Disallow creation of namespaces, whose name matches this
|
description: Disallow creation of namespaces, whose name matches this
|
||||||
regexp
|
regexp
|
||||||
type: string
|
type: string
|
||||||
userGroups:
|
rbac:
|
||||||
|
default: {}
|
||||||
|
description: Define Properties for managed ClusterRoles by Capsule
|
||||||
|
properties:
|
||||||
|
administrationClusterRoles:
|
||||||
default:
|
default:
|
||||||
- capsule.clastix.io
|
- capsule-namespace-deleter
|
||||||
description: Names of the groups for Capsule users.
|
description: The ClusterRoles applied for Administrators
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
type: array
|
type: array
|
||||||
required:
|
deleter:
|
||||||
- enableTLSReconciler
|
default: capsule-namespace-deleter
|
||||||
|
description: Name for the ClusterRole required to grant Namespace
|
||||||
|
Deletion permissions.
|
||||||
|
type: string
|
||||||
|
promotionClusterRoles:
|
||||||
|
default:
|
||||||
|
- capsule-namespace-provisioner
|
||||||
|
- capsule-namespace-deleter
|
||||||
|
description: The ClusterRoles applied for ServiceAccounts which
|
||||||
|
had owner Promotion
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
provisioner:
|
||||||
|
default: capsule-namespace-provisioner
|
||||||
|
description: Name for the ClusterRole required to grant Namespace
|
||||||
|
Provision permissions.
|
||||||
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
userGroups:
|
||||||
|
description: |-
|
||||||
|
Deprecated: use users property instead (https://projectcapsule.dev/docs/operating/setup/configuration/#users)
|
||||||
|
|
||||||
|
Names of the groups considered as Capsule users.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
userNames:
|
||||||
|
description: |-
|
||||||
|
Deprecated: use users property instead (https://projectcapsule.dev/docs/operating/setup/configuration/#users)
|
||||||
|
|
||||||
|
Names of the users considered as Capsule users.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
users:
|
||||||
|
description: |-
|
||||||
|
Define entities which are considered part of the Capsule construct
|
||||||
|
Users not mentioned here will be ignored by Capsule
|
||||||
|
items:
|
||||||
|
properties:
|
||||||
|
kind:
|
||||||
|
description: Kind of entity. Possible values are "User", "Group",
|
||||||
|
and "ServiceAccount"
|
||||||
|
enum:
|
||||||
|
- User
|
||||||
|
- Group
|
||||||
|
- ServiceAccount
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: Name of the entity.
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- kind
|
||||||
|
- name
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
required:
|
||||||
|
- cacheInvalidation
|
||||||
|
- enableTLSReconciler
|
||||||
|
- rbac
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: CapsuleConfigurationStatus defines the Capsule configuration
|
||||||
|
status.
|
||||||
|
properties:
|
||||||
|
lastCacheInvalidation:
|
||||||
|
description: Last time all caches were invalided
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
users:
|
||||||
|
description: Users which are considered Capsule Users and are bound
|
||||||
|
to the Capsule Tenant construct.
|
||||||
|
items:
|
||||||
|
properties:
|
||||||
|
kind:
|
||||||
|
description: Kind of entity. Possible values are "User", "Group",
|
||||||
|
and "ServiceAccount"
|
||||||
|
enum:
|
||||||
|
- User
|
||||||
|
- Group
|
||||||
|
- ServiceAccount
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: Name of the entity.
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- kind
|
||||||
|
- name
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- spec
|
||||||
type: object
|
type: object
|
||||||
served: true
|
served: true
|
||||||
storage: true
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.17.2
|
controller-gen.kubebuilder.io/version: v0.20.0
|
||||||
name: globaltenantresources.capsule.clastix.io
|
name: globaltenantresources.capsule.clastix.io
|
||||||
spec:
|
spec:
|
||||||
group: capsule.clastix.io
|
group: capsule.clastix.io
|
||||||
@@ -291,6 +291,8 @@ spec:
|
|||||||
- processedItems
|
- processedItems
|
||||||
- selectedTenants
|
- selectedTenants
|
||||||
type: object
|
type: object
|
||||||
|
required:
|
||||||
|
- spec
|
||||||
type: object
|
type: object
|
||||||
served: true
|
served: true
|
||||||
storage: true
|
storage: true
|
||||||
|
|||||||
257
charts/capsule/crds/capsule.clastix.io_resourcepoolclaims.yaml
Normal file
257
charts/capsule/crds/capsule.clastix.io_resourcepoolclaims.yaml
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.20.0
|
||||||
|
name: resourcepoolclaims.capsule.clastix.io
|
||||||
|
spec:
|
||||||
|
group: capsule.clastix.io
|
||||||
|
names:
|
||||||
|
kind: ResourcePoolClaim
|
||||||
|
listKind: ResourcePoolClaimList
|
||||||
|
plural: resourcepoolclaims
|
||||||
|
singular: resourcepoolclaim
|
||||||
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- additionalPrinterColumns:
|
||||||
|
- description: The ResourcePool being claimed from
|
||||||
|
jsonPath: .status.pool.name
|
||||||
|
name: Pool
|
||||||
|
type: string
|
||||||
|
- description: Ready Status
|
||||||
|
jsonPath: .status.conditions[?(@.type=="Ready")].status
|
||||||
|
name: Ready
|
||||||
|
type: string
|
||||||
|
- description: Ready Message
|
||||||
|
jsonPath: .status.conditions[?(@.type=="Ready")].message
|
||||||
|
name: Message
|
||||||
|
type: string
|
||||||
|
- description: Bound Status
|
||||||
|
jsonPath: .status.conditions[?(@.type=="Bound")].status
|
||||||
|
name: Bound
|
||||||
|
type: string
|
||||||
|
- description: Bound Message
|
||||||
|
jsonPath: .status.conditions[?(@.type=="Bound")].message
|
||||||
|
name: Reason
|
||||||
|
type: string
|
||||||
|
- jsonPath: .metadata.creationTimestamp
|
||||||
|
name: Age
|
||||||
|
type: date
|
||||||
|
name: v1beta2
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: ResourcePoolClaim is the Schema for the resourcepoolclaims API.
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: |-
|
||||||
|
APIVersion defines the versioned schema of this representation of an object.
|
||||||
|
Servers should convert recognized schemas to the latest internal value, and
|
||||||
|
may reject unrecognized values.
|
||||||
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: |-
|
||||||
|
Kind is a string value representing the REST resource this object represents.
|
||||||
|
Servers may infer this from the endpoint the client submits requests to.
|
||||||
|
Cannot be updated.
|
||||||
|
In CamelCase.
|
||||||
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
properties:
|
||||||
|
claim:
|
||||||
|
additionalProperties:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
description: Amount which should be claimed for the resourcequota
|
||||||
|
type: object
|
||||||
|
pool:
|
||||||
|
description: |-
|
||||||
|
If there's the possability to claim from multiple global Quotas
|
||||||
|
You must be specific about which one you want to claim resources from
|
||||||
|
Once bound to a ResourcePool, this field is immutable
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- claim
|
||||||
|
- pool
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: ResourceQuotaClaimStatus defines the observed state of ResourceQuotaClaim.
|
||||||
|
properties:
|
||||||
|
allocation:
|
||||||
|
description: Tracks the Usage from Claimed from this claim and available
|
||||||
|
resources
|
||||||
|
properties:
|
||||||
|
available:
|
||||||
|
additionalProperties:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
description: Used to track the usage of the resource in the pool
|
||||||
|
(diff hard - claimed). May be used for further automation
|
||||||
|
type: object
|
||||||
|
hard:
|
||||||
|
additionalProperties:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
description: |-
|
||||||
|
Hard is the set of enforced hard limits for each named resource.
|
||||||
|
More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/
|
||||||
|
type: object
|
||||||
|
used:
|
||||||
|
additionalProperties:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
description: Used is the current observed total usage of the resource
|
||||||
|
in the namespace.
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
condition:
|
||||||
|
description: 'Deprecated: Use Conditions'
|
||||||
|
properties:
|
||||||
|
lastTransitionTime:
|
||||||
|
description: |-
|
||||||
|
lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||||
|
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
description: |-
|
||||||
|
message is a human readable message indicating details about the transition.
|
||||||
|
This may be an empty string.
|
||||||
|
maxLength: 32768
|
||||||
|
type: string
|
||||||
|
observedGeneration:
|
||||||
|
description: |-
|
||||||
|
observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||||
|
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||||
|
with respect to the current state of the instance.
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
type: integer
|
||||||
|
reason:
|
||||||
|
description: |-
|
||||||
|
reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||||
|
Producers of specific condition types may define expected values and meanings for this field,
|
||||||
|
and whether the values are considered a guaranteed API.
|
||||||
|
The value should be a CamelCase string.
|
||||||
|
This field may not be empty.
|
||||||
|
maxLength: 1024
|
||||||
|
minLength: 1
|
||||||
|
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||||
|
type: string
|
||||||
|
status:
|
||||||
|
description: status of the condition, one of True, False, Unknown.
|
||||||
|
enum:
|
||||||
|
- "True"
|
||||||
|
- "False"
|
||||||
|
- Unknown
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
maxLength: 316
|
||||||
|
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- lastTransitionTime
|
||||||
|
- message
|
||||||
|
- reason
|
||||||
|
- status
|
||||||
|
- type
|
||||||
|
type: object
|
||||||
|
conditions:
|
||||||
|
description: Conditions for the resource claim
|
||||||
|
items:
|
||||||
|
description: Condition contains details for one aspect of the current
|
||||||
|
state of this API Resource.
|
||||||
|
properties:
|
||||||
|
lastTransitionTime:
|
||||||
|
description: |-
|
||||||
|
lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||||
|
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
description: |-
|
||||||
|
message is a human readable message indicating details about the transition.
|
||||||
|
This may be an empty string.
|
||||||
|
maxLength: 32768
|
||||||
|
type: string
|
||||||
|
observedGeneration:
|
||||||
|
description: |-
|
||||||
|
observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||||
|
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||||
|
with respect to the current state of the instance.
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
type: integer
|
||||||
|
reason:
|
||||||
|
description: |-
|
||||||
|
reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||||
|
Producers of specific condition types may define expected values and meanings for this field,
|
||||||
|
and whether the values are considered a guaranteed API.
|
||||||
|
The value should be a CamelCase string.
|
||||||
|
This field may not be empty.
|
||||||
|
maxLength: 1024
|
||||||
|
minLength: 1
|
||||||
|
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||||
|
type: string
|
||||||
|
status:
|
||||||
|
description: status of the condition, one of True, False, Unknown.
|
||||||
|
enum:
|
||||||
|
- "True"
|
||||||
|
- "False"
|
||||||
|
- Unknown
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
maxLength: 316
|
||||||
|
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- lastTransitionTime
|
||||||
|
- message
|
||||||
|
- reason
|
||||||
|
- status
|
||||||
|
- type
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
pool:
|
||||||
|
description: Reference to the GlobalQuota being claimed from
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: Name of the referent.
|
||||||
|
maxLength: 63
|
||||||
|
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
|
||||||
|
type: string
|
||||||
|
uid:
|
||||||
|
description: UID of the tracked Tenant to pin point tracking
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- uid
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- conditions
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- spec
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
401
charts/capsule/crds/capsule.clastix.io_resourcepools.yaml
Normal file
401
charts/capsule/crds/capsule.clastix.io_resourcepools.yaml
Normal file
@@ -0,0 +1,401 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.20.0
|
||||||
|
name: resourcepools.capsule.clastix.io
|
||||||
|
spec:
|
||||||
|
group: capsule.clastix.io
|
||||||
|
names:
|
||||||
|
kind: ResourcePool
|
||||||
|
listKind: ResourcePoolList
|
||||||
|
plural: resourcepools
|
||||||
|
shortNames:
|
||||||
|
- quotapool
|
||||||
|
singular: resourcepool
|
||||||
|
scope: Cluster
|
||||||
|
versions:
|
||||||
|
- additionalPrinterColumns:
|
||||||
|
- description: The total amount of Claims bound
|
||||||
|
jsonPath: .status.claimCount
|
||||||
|
name: Claims
|
||||||
|
type: integer
|
||||||
|
- description: The total amount of Namespaces considered
|
||||||
|
jsonPath: .status.namespaceCount
|
||||||
|
name: Namespaces
|
||||||
|
type: integer
|
||||||
|
- description: Reconcile Status
|
||||||
|
jsonPath: .status.conditions[?(@.type=="Ready")].status
|
||||||
|
name: Ready
|
||||||
|
type: string
|
||||||
|
- description: Reconcile Message
|
||||||
|
jsonPath: .status.conditions[?(@.type=="Ready")].message
|
||||||
|
name: Status
|
||||||
|
type: string
|
||||||
|
- description: Age
|
||||||
|
jsonPath: .metadata.creationTimestamp
|
||||||
|
name: Age
|
||||||
|
type: date
|
||||||
|
name: v1beta2
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: |-
|
||||||
|
Resourcepools allows you to define a set of resources as known from ResoureQuotas. The Resourcepools are defined at cluster-scope an should
|
||||||
|
be administrated by cluster-administrators. However they create an interface, where cluster-administrators can define
|
||||||
|
from which namespaces resources from a Resourcepool can be claimed. The claiming is done via a namespaced CRD called ResourcePoolClaim. Then
|
||||||
|
it's up the group of users within these namespaces, to manage the resources they consume per namespace. Each Resourcepool provisions a ResourceQuotainto all the selected namespaces. Then essentially the ResourcePoolClaims, when they can be assigned to the ResourcePool stack resources on top of that
|
||||||
|
ResourceQuota based on the namspace, where the ResourcePoolClaim was made from.
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: |-
|
||||||
|
APIVersion defines the versioned schema of this representation of an object.
|
||||||
|
Servers should convert recognized schemas to the latest internal value, and
|
||||||
|
may reject unrecognized values.
|
||||||
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: |-
|
||||||
|
Kind is a string value representing the REST resource this object represents.
|
||||||
|
Servers may infer this from the endpoint the client submits requests to.
|
||||||
|
Cannot be updated.
|
||||||
|
In CamelCase.
|
||||||
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: ResourcePoolSpec.
|
||||||
|
properties:
|
||||||
|
config:
|
||||||
|
default: {}
|
||||||
|
description: Additional Configuration
|
||||||
|
properties:
|
||||||
|
defaultsZero:
|
||||||
|
default: false
|
||||||
|
description: With this option all resources which can be allocated
|
||||||
|
are set to 0 for the resourcequota defaults. (Default false)
|
||||||
|
type: boolean
|
||||||
|
deleteBoundResources:
|
||||||
|
default: false
|
||||||
|
description: |-
|
||||||
|
When a resourcepool is deleted, the resourceclaims bound to it are disassociated from the resourcepool but not deleted.
|
||||||
|
By Enabling this option, the resourceclaims will be deleted when the resourcepool is deleted, if they are in bound state. (Default false)
|
||||||
|
type: boolean
|
||||||
|
orderedQueue:
|
||||||
|
default: false
|
||||||
|
description: |-
|
||||||
|
Claims are queued whenever they are allocated to a pool. A pool tries to allocate claims in order based on their
|
||||||
|
creation date. But no matter their creation time, if a claim is requesting too much resources it's put into the queue
|
||||||
|
but if a lower priority claim still has enough space in the available resources, it will be able to claim them. Eventough
|
||||||
|
it's priority was lower
|
||||||
|
Enabling this option respects to Order. Meaning the Creationtimestamp matters and if a resource is put into the queue, no
|
||||||
|
other claim can claim the same resources with lower priority. (Default false)
|
||||||
|
type: boolean
|
||||||
|
type: object
|
||||||
|
defaults:
|
||||||
|
additionalProperties:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
description: |-
|
||||||
|
The Defaults given for each namespace, the default is not counted towards the total allocation
|
||||||
|
When you use claims it's recommended to provision Defaults as the prevent the scheduling of any resources
|
||||||
|
type: object
|
||||||
|
quota:
|
||||||
|
description: Define the resourcequota served by this resourcepool.
|
||||||
|
properties:
|
||||||
|
hard:
|
||||||
|
additionalProperties:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
description: |-
|
||||||
|
hard is the set of desired hard limits for each named resource.
|
||||||
|
More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/
|
||||||
|
type: object
|
||||||
|
scopeSelector:
|
||||||
|
description: |-
|
||||||
|
scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota
|
||||||
|
but expressed using ScopeSelectorOperator in combination with possible values.
|
||||||
|
For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched.
|
||||||
|
properties:
|
||||||
|
matchExpressions:
|
||||||
|
description: A list of scope selector requirements by scope
|
||||||
|
of the resources.
|
||||||
|
items:
|
||||||
|
description: |-
|
||||||
|
A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator
|
||||||
|
that relates the scope name and values.
|
||||||
|
properties:
|
||||||
|
operator:
|
||||||
|
description: |-
|
||||||
|
Represents a scope's relationship to a set of values.
|
||||||
|
Valid operators are In, NotIn, Exists, DoesNotExist.
|
||||||
|
type: string
|
||||||
|
scopeName:
|
||||||
|
description: The name of the scope that the selector
|
||||||
|
applies to.
|
||||||
|
type: string
|
||||||
|
values:
|
||||||
|
description: |-
|
||||||
|
An array of string values. If the operator is In or NotIn,
|
||||||
|
the values array must be non-empty. If the operator is Exists or DoesNotExist,
|
||||||
|
the values array must be empty.
|
||||||
|
This array is replaced during a strategic merge patch.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-type: atomic
|
||||||
|
required:
|
||||||
|
- operator
|
||||||
|
- scopeName
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-type: atomic
|
||||||
|
type: object
|
||||||
|
x-kubernetes-map-type: atomic
|
||||||
|
scopes:
|
||||||
|
description: |-
|
||||||
|
A collection of filters that must match each object tracked by a quota.
|
||||||
|
If not specified, the quota matches all objects.
|
||||||
|
items:
|
||||||
|
description: A ResourceQuotaScope defines a filter that must
|
||||||
|
match each object tracked by a quota
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-type: atomic
|
||||||
|
type: object
|
||||||
|
selectors:
|
||||||
|
description: Selector to match the namespaces that should be managed
|
||||||
|
by the GlobalResourceQuota
|
||||||
|
items:
|
||||||
|
description: Selector for resources and their labels or selecting
|
||||||
|
origin namespaces
|
||||||
|
properties:
|
||||||
|
matchExpressions:
|
||||||
|
description: matchExpressions is a list of label selector requirements.
|
||||||
|
The requirements are ANDed.
|
||||||
|
items:
|
||||||
|
description: |-
|
||||||
|
A label selector requirement is a selector that contains values, a key, and an operator that
|
||||||
|
relates the key and values.
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
description: key is the label key that the selector applies
|
||||||
|
to.
|
||||||
|
type: string
|
||||||
|
operator:
|
||||||
|
description: |-
|
||||||
|
operator represents a key's relationship to a set of values.
|
||||||
|
Valid operators are In, NotIn, Exists and DoesNotExist.
|
||||||
|
type: string
|
||||||
|
values:
|
||||||
|
description: |-
|
||||||
|
values is an array of string values. If the operator is In or NotIn,
|
||||||
|
the values array must be non-empty. If the operator is Exists or DoesNotExist,
|
||||||
|
the values array must be empty. This array is replaced during a strategic
|
||||||
|
merge patch.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-type: atomic
|
||||||
|
required:
|
||||||
|
- key
|
||||||
|
- operator
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-type: atomic
|
||||||
|
matchLabels:
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
|
||||||
|
map is equivalent to an element of matchExpressions, whose key field is "key", the
|
||||||
|
operator is "In", and the values array contains only "value". The requirements are ANDed.
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
x-kubernetes-map-type: atomic
|
||||||
|
type: array
|
||||||
|
required:
|
||||||
|
- quota
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: GlobalResourceQuotaStatus defines the observed state of GlobalResourceQuota.
|
||||||
|
properties:
|
||||||
|
allocation:
|
||||||
|
description: Tracks the Usage from Claimed against what has been granted
|
||||||
|
from the pool
|
||||||
|
properties:
|
||||||
|
available:
|
||||||
|
additionalProperties:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
description: Used to track the usage of the resource in the pool
|
||||||
|
(diff hard - claimed). May be used for further automation
|
||||||
|
type: object
|
||||||
|
hard:
|
||||||
|
additionalProperties:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
description: |-
|
||||||
|
Hard is the set of enforced hard limits for each named resource.
|
||||||
|
More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/
|
||||||
|
type: object
|
||||||
|
used:
|
||||||
|
additionalProperties:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
description: Used is the current observed total usage of the resource
|
||||||
|
in the namespace.
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
claimCount:
|
||||||
|
default: 0
|
||||||
|
description: Amount of claims
|
||||||
|
type: integer
|
||||||
|
claims:
|
||||||
|
additionalProperties:
|
||||||
|
items:
|
||||||
|
description: ResourceQuotaClaimStatus defines the observed state
|
||||||
|
of ResourceQuotaClaim.
|
||||||
|
properties:
|
||||||
|
claims:
|
||||||
|
additionalProperties:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
description: Claimed resources
|
||||||
|
type: object
|
||||||
|
name:
|
||||||
|
description: Name of the referent.
|
||||||
|
maxLength: 63
|
||||||
|
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
|
||||||
|
type: string
|
||||||
|
namespace:
|
||||||
|
description: Namespace of the referent.
|
||||||
|
maxLength: 253
|
||||||
|
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
|
||||||
|
type: string
|
||||||
|
uid:
|
||||||
|
description: UID of the tracked Tenant to pin point tracking
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- namespace
|
||||||
|
- uid
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
description: Tracks the quotas for the Resource.
|
||||||
|
type: object
|
||||||
|
conditions:
|
||||||
|
description: Conditions for the resource claim
|
||||||
|
items:
|
||||||
|
description: Condition contains details for one aspect of the current
|
||||||
|
state of this API Resource.
|
||||||
|
properties:
|
||||||
|
lastTransitionTime:
|
||||||
|
description: |-
|
||||||
|
lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||||
|
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
description: |-
|
||||||
|
message is a human readable message indicating details about the transition.
|
||||||
|
This may be an empty string.
|
||||||
|
maxLength: 32768
|
||||||
|
type: string
|
||||||
|
observedGeneration:
|
||||||
|
description: |-
|
||||||
|
observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||||
|
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||||
|
with respect to the current state of the instance.
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
type: integer
|
||||||
|
reason:
|
||||||
|
description: |-
|
||||||
|
reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||||
|
Producers of specific condition types may define expected values and meanings for this field,
|
||||||
|
and whether the values are considered a guaranteed API.
|
||||||
|
The value should be a CamelCase string.
|
||||||
|
This field may not be empty.
|
||||||
|
maxLength: 1024
|
||||||
|
minLength: 1
|
||||||
|
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||||
|
type: string
|
||||||
|
status:
|
||||||
|
description: status of the condition, one of True, False, Unknown.
|
||||||
|
enum:
|
||||||
|
- "True"
|
||||||
|
- "False"
|
||||||
|
- Unknown
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
maxLength: 316
|
||||||
|
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- lastTransitionTime
|
||||||
|
- message
|
||||||
|
- reason
|
||||||
|
- status
|
||||||
|
- type
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
exhaustions:
|
||||||
|
additionalProperties:
|
||||||
|
properties:
|
||||||
|
available:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
description: Available Resources to be claimed
|
||||||
|
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
requesting:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
description: Requesting Resources
|
||||||
|
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
type: object
|
||||||
|
description: Exhaustions from claims associated with the pool
|
||||||
|
type: object
|
||||||
|
namespaceCount:
|
||||||
|
default: 0
|
||||||
|
description: How many namespaces are considered
|
||||||
|
type: integer
|
||||||
|
namespaces:
|
||||||
|
description: Namespaces which are considered for claims
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
required:
|
||||||
|
- conditions
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- spec
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
94
charts/capsule/crds/capsule.clastix.io_rulestatuses.yaml
Normal file
94
charts/capsule/crds/capsule.clastix.io_rulestatuses.yaml
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.20.0
|
||||||
|
name: rulestatuses.capsule.clastix.io
|
||||||
|
spec:
|
||||||
|
group: capsule.clastix.io
|
||||||
|
names:
|
||||||
|
kind: RuleStatus
|
||||||
|
listKind: RuleStatusList
|
||||||
|
plural: rulestatuses
|
||||||
|
singular: rulestatus
|
||||||
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- additionalPrinterColumns:
|
||||||
|
- description: Age
|
||||||
|
jsonPath: .metadata.creationTimestamp
|
||||||
|
name: Age
|
||||||
|
type: date
|
||||||
|
name: v1beta2
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: |-
|
||||||
|
APIVersion defines the versioned schema of this representation of an object.
|
||||||
|
Servers should convert recognized schemas to the latest internal value, and
|
||||||
|
may reject unrecognized values.
|
||||||
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: |-
|
||||||
|
Kind is a string value representing the REST resource this object represents.
|
||||||
|
Servers may infer this from the endpoint the client submits requests to.
|
||||||
|
Cannot be updated.
|
||||||
|
In CamelCase.
|
||||||
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: RuleStatus contains the accumulated rules applying to namespace
|
||||||
|
it's deployed in.
|
||||||
|
properties:
|
||||||
|
rule:
|
||||||
|
description: Managed Enforcement properties per Namespace (aggregated
|
||||||
|
from rules)
|
||||||
|
properties:
|
||||||
|
enforce:
|
||||||
|
description: Enforcement Rules applied
|
||||||
|
properties:
|
||||||
|
registries:
|
||||||
|
description: |-
|
||||||
|
Define registries which are allowed to be used within this tenant
|
||||||
|
The rules are aggregated, since you can use Regular Expressions the match registry endpoints
|
||||||
|
items:
|
||||||
|
properties:
|
||||||
|
policy:
|
||||||
|
description: Allowed PullPolicy for the given registry.
|
||||||
|
Supplying no value allows all policies.
|
||||||
|
items:
|
||||||
|
description: PullPolicy describes a policy for if/when
|
||||||
|
to pull a container image
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
url:
|
||||||
|
description: OCI Registry endpoint, is treated as regular
|
||||||
|
expression.
|
||||||
|
type: string
|
||||||
|
validation:
|
||||||
|
default:
|
||||||
|
- pod/images
|
||||||
|
- pod/volumes
|
||||||
|
description: Requesting Resources
|
||||||
|
items:
|
||||||
|
enum:
|
||||||
|
- pod/images
|
||||||
|
- pod/volumes
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
required:
|
||||||
|
- url
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
82
charts/capsule/crds/capsule.clastix.io_tenantowners.yaml
Normal file
82
charts/capsule/crds/capsule.clastix.io_tenantowners.yaml
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.20.0
|
||||||
|
name: tenantowners.capsule.clastix.io
|
||||||
|
spec:
|
||||||
|
group: capsule.clastix.io
|
||||||
|
names:
|
||||||
|
kind: TenantOwner
|
||||||
|
listKind: TenantOwnerList
|
||||||
|
plural: tenantowners
|
||||||
|
singular: tenantowner
|
||||||
|
scope: Cluster
|
||||||
|
versions:
|
||||||
|
- name: v1beta2
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: TenantOwner is the Schema for the tenantowners API.
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: |-
|
||||||
|
APIVersion defines the versioned schema of this representation of an object.
|
||||||
|
Servers should convert recognized schemas to the latest internal value, and
|
||||||
|
may reject unrecognized values.
|
||||||
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: |-
|
||||||
|
Kind is a string value representing the REST resource this object represents.
|
||||||
|
Servers may infer this from the endpoint the client submits requests to.
|
||||||
|
Cannot be updated.
|
||||||
|
In CamelCase.
|
||||||
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: spec defines the desired state of TenantOwner.
|
||||||
|
properties:
|
||||||
|
aggregate:
|
||||||
|
default: true
|
||||||
|
description: |-
|
||||||
|
Adds the given subject as capsule user. When enabled this subject does not have to be
|
||||||
|
mentioned in the CapsuleConfiguration as Capsule User. In almost all scenarios Tenant Owners
|
||||||
|
must be Capsule Users.
|
||||||
|
type: boolean
|
||||||
|
clusterRoles:
|
||||||
|
default:
|
||||||
|
- admin
|
||||||
|
- capsule-namespace-deleter
|
||||||
|
description: Defines additional cluster-roles for the specific Owner.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
kind:
|
||||||
|
description: Kind of entity. Possible values are "User", "Group",
|
||||||
|
and "ServiceAccount"
|
||||||
|
enum:
|
||||||
|
- User
|
||||||
|
- Group
|
||||||
|
- ServiceAccount
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: Name of the entity.
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- aggregate
|
||||||
|
- kind
|
||||||
|
- name
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: status defines the observed state of TenantOwner.
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- spec
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
|||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
controller-gen.kubebuilder.io/version: v0.17.2
|
controller-gen.kubebuilder.io/version: v0.20.0
|
||||||
name: tenantresources.capsule.clastix.io
|
name: tenantresources.capsule.clastix.io
|
||||||
spec:
|
spec:
|
||||||
group: capsule.clastix.io
|
group: capsule.clastix.io
|
||||||
@@ -239,6 +239,8 @@ spec:
|
|||||||
required:
|
required:
|
||||||
- processedItems
|
- processedItems
|
||||||
type: object
|
type: object
|
||||||
|
required:
|
||||||
|
- spec
|
||||||
type: object
|
type: object
|
||||||
served: true
|
served: true
|
||||||
storage: true
|
storage: true
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
1590
charts/capsule/dashboards/resourcepools-dashboard.json
Normal file
1590
charts/capsule/dashboards/resourcepools-dashboard.json
Normal file
File diff suppressed because it is too large
Load Diff
1083
charts/capsule/diagnostics/admission-dashboard.json
Normal file
1083
charts/capsule/diagnostics/admission-dashboard.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -53,6 +53,15 @@ app.kubernetes.io/name: {{ include "capsule.name" . }}
|
|||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Release Annotations
|
||||||
|
*/}}
|
||||||
|
{{- define "capsule.releaseAnnotations" -}}
|
||||||
|
meta.helm.sh/release-name: {{ $.Release.Name }}
|
||||||
|
meta.helm.sh/release-namespace: {{ .Release.Namespace }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
ServiceAccount annotations
|
ServiceAccount annotations
|
||||||
*/}}
|
*/}}
|
||||||
@@ -146,6 +155,24 @@ service:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Capsule Webhook service (Without Path)
|
||||||
|
|
||||||
|
*/}}
|
||||||
|
{{- define "capsule.webhooks.serviceConfig" -}}
|
||||||
|
{{- include "capsule.webhooks.cabundle" $ | nindent 0 }}
|
||||||
|
{{- if $.Values.webhooks.service.url }}
|
||||||
|
url: {{ trimSuffix "/" $.Values.webhooks.service.url }}
|
||||||
|
{{- else }}
|
||||||
|
service:
|
||||||
|
name: {{ default (printf "%s-webhook-service" (include "capsule.fullname" $)) $.Values.webhooks.service.name }}
|
||||||
|
namespace: {{ default $.Release.Namespace $.Values.webhooks.service.namespace }}
|
||||||
|
port: {{ default 443 $.Values.webhooks.service.port }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
Capsule Webhook endpoint CA Bundle
|
Capsule Webhook endpoint CA Bundle
|
||||||
*/}}
|
*/}}
|
||||||
@@ -156,3 +183,37 @@ caBundle: {{ $.Values.webhooks.service.caBundle -}}
|
|||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
|
|
||||||
|
{{- define "capsule.crdsSizeHash" -}}
|
||||||
|
{{- $paths := list -}}
|
||||||
|
{{- range $p, $_ := .Files.Glob "crds/**.yaml" }}
|
||||||
|
{{- $paths = append $paths $p -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- $paths = sortAlpha $paths -}}
|
||||||
|
|
||||||
|
{{- $sizes := list -}}
|
||||||
|
{{- range $paths }}
|
||||||
|
{{- $sizes = append $sizes (len ($.Files.Get .)) -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- $joined := join "," $sizes -}}
|
||||||
|
{{- sha256sum $joined -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- define "admission.labels" -}}
|
||||||
|
{{- with $.Values.webhooks.labels }}
|
||||||
|
{{- toYaml . | nindent 0 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{- define "admission.annotations" -}}
|
||||||
|
{{- if and ($.Values.certManager.generateCertificates) (not $.Values.webhooks.service.caBundle) }}
|
||||||
|
cert-manager.io/inject-ca-from: {{ $.Release.Namespace }}/{{ include "capsule.fullname" $ }}-webhook-cert
|
||||||
|
{{- end }}
|
||||||
|
{{- with $.Values.customAnnotations }}
|
||||||
|
{{- toYaml . | nindent 0 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with $.Values.webhooks.annotations }}
|
||||||
|
{{- toYaml . | nindent 0 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|||||||
120
charts/capsule/templates/_pod.tpl
Normal file
120
charts/capsule/templates/_pod.tpl
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
{{- define "capsule.pod" -}}
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
{{- with .Values.podAnnotations }}
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.crds.install }}
|
||||||
|
projectcapsule.dev/crds-size-hash: {{ include "capsule.crdsSizeHash" . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
labels:
|
||||||
|
{{- include "capsule.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.podLabels }}
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- with .Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
serviceAccountName: {{ include "capsule.serviceAccountName" . }}
|
||||||
|
{{- if .Values.podSecurityContext.enabled }}
|
||||||
|
securityContext: {{- omit .Values.podSecurityContext "enabled" | toYaml | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if not .Values.manager.hostUsers }}
|
||||||
|
hostUsers: {{ .Values.manager.hostUsers }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.manager.hostNetwork }}
|
||||||
|
hostNetwork: true
|
||||||
|
dnsPolicy: ClusterFirstWithHostNet
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.manager.hostPID }}
|
||||||
|
hostPID: {{ .Values.manager.hostPID }}
|
||||||
|
{{- else }}
|
||||||
|
hostPID: false
|
||||||
|
{{- end }}
|
||||||
|
priorityClassName: {{ .Values.priorityClassName }}
|
||||||
|
{{- with .Values.nodeSelector }}
|
||||||
|
nodeSelector:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.tolerations }}
|
||||||
|
tolerations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.affinity }}
|
||||||
|
affinity:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.topologySpreadConstraints }}
|
||||||
|
topologySpreadConstraints:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
volumes:
|
||||||
|
- name: cert
|
||||||
|
secret:
|
||||||
|
defaultMode: 420
|
||||||
|
secretName: {{ include "capsule.secretTlsName" . }}
|
||||||
|
{{- if .Values.manager.volumes }}
|
||||||
|
{{- toYaml .Values.manager.volumes | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
containers:
|
||||||
|
- name: manager
|
||||||
|
args:
|
||||||
|
- --webhook-port={{ .Values.manager.webhookPort }}
|
||||||
|
- --zap-log-level={{ default 4 .Values.manager.options.logLevel }}
|
||||||
|
- --configuration-name={{ .Values.manager.options.capsuleConfiguration }}
|
||||||
|
- --workers={{ .Values.manager.options.workers }}
|
||||||
|
{{- with .Values.manager.extraArgs }}
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
image: {{ include "capsule.managerFullyQualifiedDockerImage" . }}
|
||||||
|
imagePullPolicy: {{ .Values.manager.image.pullPolicy }}
|
||||||
|
env:
|
||||||
|
- name: NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
- name: SERVICE_ACCOUNT
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: spec.serviceAccountName
|
||||||
|
{{- with .Values.manager.env }}
|
||||||
|
{{- toYaml . | nindent 6 }}
|
||||||
|
{{- end }}
|
||||||
|
ports:
|
||||||
|
{{- if not (.Values.manager.hostNetwork) }}
|
||||||
|
- name: webhook-server
|
||||||
|
containerPort: {{ .Values.manager.webhookPort }}
|
||||||
|
protocol: TCP
|
||||||
|
- name: metrics
|
||||||
|
containerPort: 8080
|
||||||
|
protocol: TCP
|
||||||
|
- name: health-api
|
||||||
|
containerPort: 10080
|
||||||
|
protocol: TCP
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.manager.ports }}
|
||||||
|
{{- . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
livenessProbe:
|
||||||
|
{{- toYaml .Values.manager.livenessProbe | nindent 8 }}
|
||||||
|
readinessProbe:
|
||||||
|
{{- toYaml .Values.manager.readinessProbe | nindent 8 }}
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /tmp/k8s-webhook-server/serving-certs
|
||||||
|
name: cert
|
||||||
|
readOnly: true
|
||||||
|
{{- if .Values.manager.volumeMounts }}
|
||||||
|
{{- toYaml .Values.manager.volumeMounts | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.manager.resources | nindent 8 }}
|
||||||
|
{{- if .Values.manager.securityContext }}
|
||||||
|
securityContext:
|
||||||
|
{{- omit .Values.manager.securityContext "enabled" | toYaml | nindent 8 }}
|
||||||
|
{{- else if .Values.securityContext.enabled }}
|
||||||
|
securityContext:
|
||||||
|
{{- omit .Values.securityContext "enabled" | toYaml | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end -}}
|
||||||
@@ -4,6 +4,7 @@ apiVersion: cert-manager.io/v1
|
|||||||
kind: Issuer
|
kind: Issuer
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "capsule.fullname" . }}-webhook-selfsigned
|
name: {{ include "capsule.fullname" . }}-webhook-selfsigned
|
||||||
|
namespace: {{ $.Release.Namespace }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "capsule.labels" . | nindent 4 }}
|
{{- include "capsule.labels" . | nindent 4 }}
|
||||||
{{- with .Values.customAnnotations }}
|
{{- with .Values.customAnnotations }}
|
||||||
@@ -17,6 +18,7 @@ apiVersion: cert-manager.io/v1
|
|||||||
kind: Certificate
|
kind: Certificate
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "capsule.fullname" . }}-webhook-cert
|
name: {{ include "capsule.fullname" . }}-webhook-cert
|
||||||
|
namespace: {{ $.Release.Namespace }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "capsule.labels" . | nindent 4 }}
|
{{- include "capsule.labels" . | nindent 4 }}
|
||||||
{{- with .Values.customAnnotations }}
|
{{- with .Values.customAnnotations }}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
|
namespace: {{ $.Release.Namespace }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "capsule.labels" . | nindent 4 }}
|
{{- include "capsule.labels" . | nindent 4 }}
|
||||||
{{- with .Values.customAnnotations }}
|
{{- with .Values.customAnnotations }}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user