mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-08-19 04:26:45 +00:00
feat: upstream enterprise preview (#1841)
feat: upstream enterprise preview --------- Signed-off-by: Oliver Baehler <oliver@sudo-i.net> Co-authored-by: CorentinPtrl <pitrel.corentin@gmail.com>
This commit is contained in:
co-authored by
CorentinPtrl
parent
7a65ab7afc
commit
cc4fb45d70
@@ -220,6 +220,134 @@ spec:
|
||||
|
||||
return obj
|
||||
|
||||
resource.customizations.health.capsule.clastix.io_GlobalTenantResource: |
|
||||
hs = {}
|
||||
if obj.status ~= nil then
|
||||
if obj.status.conditions ~= nil then
|
||||
for i, condition in ipairs(obj.status.conditions) do
|
||||
if condition.type == "Cordoned" and condition.status == "True" then
|
||||
hs.status = "Suspended"
|
||||
hs.message = condition.message
|
||||
return hs
|
||||
end
|
||||
end
|
||||
for i, condition in ipairs(obj.status.conditions) do
|
||||
if condition.type == "Ready" and condition.status == "False" then
|
||||
hs.status = "Degraded"
|
||||
hs.message = condition.message
|
||||
return hs
|
||||
end
|
||||
if condition.type == "Ready" and condition.status == "True" then
|
||||
hs.status = "Healthy"
|
||||
hs.message = condition.message
|
||||
return hs
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
hs.status = "Progressing"
|
||||
hs.message = "Waiting for Status"
|
||||
return hs
|
||||
|
||||
resource.customizations.actions.capsule.clastix.io_GlobalTenantResource: |
|
||||
mergeBuiltinActions: true
|
||||
discovery.lua: |
|
||||
actions = {}
|
||||
|
||||
actions["cordon"] = {
|
||||
["iconClass"] = "fa fa-solid fa-pause",
|
||||
["disabled"] = true,
|
||||
}
|
||||
actions["uncordon"] = {
|
||||
["iconClass"] = "fa fa-solid fa-play",
|
||||
["disabled"] = true,
|
||||
}
|
||||
actions["reconcile"] = {
|
||||
["iconClass"] = "fa fa-solid fa-sync",
|
||||
["disabled"] = false,
|
||||
}
|
||||
|
||||
local suspend = false
|
||||
if obj.spec ~= nil and obj.spec.cordoned ~= nil then
|
||||
suspend = obj.spec.cordoned
|
||||
end
|
||||
|
||||
if suspend then
|
||||
actions["uncordon"]["disabled"] = false
|
||||
else
|
||||
actions["cordon"]["disabled"] = false
|
||||
end
|
||||
|
||||
return actions
|
||||
|
||||
definitions:
|
||||
- name: cordon
|
||||
action.lua: |
|
||||
if obj.spec == nil then
|
||||
obj.spec = {}
|
||||
end
|
||||
obj.spec.cordoned = true
|
||||
return obj
|
||||
|
||||
- name: uncordon
|
||||
action.lua: |
|
||||
if obj.spec ~= nil and obj.spec.cordoned ~= nil and obj.spec.cordoned then
|
||||
obj.spec.cordoned = false
|
||||
end
|
||||
return obj
|
||||
|
||||
- name: reconcile
|
||||
action.lua: |
|
||||
if obj.metadata == nil then
|
||||
obj.metadata = {}
|
||||
end
|
||||
if obj.metadata.annotations == nil then
|
||||
obj.metadata.annotations = {}
|
||||
end
|
||||
|
||||
local key = "reconcile.projectcapsule.dev/requested"
|
||||
|
||||
local ts = nil
|
||||
if os ~= nil and os.time ~= nil then
|
||||
ts = tostring(os.time())
|
||||
else
|
||||
ts = "true"
|
||||
end
|
||||
|
||||
obj.metadata.annotations[key] = ts
|
||||
return obj
|
||||
|
||||
|
||||
resource.customizations.health.capsule.clastix.io_TenantResource: |
|
||||
hs = {}
|
||||
if obj.status ~= nil then
|
||||
if obj.status.conditions ~= nil then
|
||||
for i, condition in ipairs(obj.status.conditions) do
|
||||
if condition.type == "Cordoned" and condition.status == "True" then
|
||||
hs.status = "Suspended"
|
||||
hs.message = condition.message
|
||||
return hs
|
||||
end
|
||||
end
|
||||
for i, condition in ipairs(obj.status.conditions) do
|
||||
if condition.type == "Ready" and condition.status == "False" then
|
||||
hs.status = "Degraded"
|
||||
hs.message = condition.message
|
||||
return hs
|
||||
end
|
||||
if condition.type == "Ready" and condition.status == "True" then
|
||||
hs.status = "Healthy"
|
||||
hs.message = condition.message
|
||||
return hs
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
hs.status = "Progressing"
|
||||
hs.message = "Waiting for Status"
|
||||
return hs
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
apiVersion: capsule.clastix.io/v1beta2
|
||||
kind: GlobalCustomQuota
|
||||
metadata:
|
||||
name: storage-aggregate
|
||||
spec:
|
||||
limit: 5Gi
|
||||
namespaceSelectors:
|
||||
- matchLabels:
|
||||
capsule.clastix.io/tenant: wind
|
||||
sources:
|
||||
- apiVersion: v1
|
||||
kind: Pod
|
||||
op: add
|
||||
path: ".spec.volumes[*].ephemeral.volumeClaimTemplate.spec.resources.requests.storage"
|
||||
|
||||
- apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
op: add
|
||||
path: ".spec.resources.requests.storage"
|
||||
selectors:
|
||||
- fieldSelectors:
|
||||
- '.spec.accessModes[?(@=="ReadWriteOnce")]'
|
||||
---
|
||||
apiVersion: capsule.clastix.io/v1beta2
|
||||
kind: GlobalCustomQuota
|
||||
metadata:
|
||||
name: cpu-limits
|
||||
spec:
|
||||
limit: 5
|
||||
namespaceSelectors:
|
||||
- matchLabels:
|
||||
capsule.clastix.io/tenant: wind
|
||||
sources:
|
||||
- apiVersion: "v1"
|
||||
kind: Pod
|
||||
op: add
|
||||
path: .spec.containers[*].resources.limits.cpu
|
||||
- apiVersion: "v1"
|
||||
kind: Pod
|
||||
op: add
|
||||
path: .spec.initContainers[*].resources.limits.cpu
|
||||
@@ -5,3 +5,5 @@ resources:
|
||||
- tenants.yaml
|
||||
- resource.yaml
|
||||
- pools.yaml
|
||||
- rbac.yaml
|
||||
- custom-quotas.yaml
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: configmap-replicator
|
||||
labels:
|
||||
projectcapsule.dev/aggregate-to-controller: "true"
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["configmaps"]
|
||||
verbs: ["get", "create", "patch", "watch", "list", "delete"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: secret-replicator
|
||||
labels:
|
||||
projectcapsule.dev/aggregate-to-controller: "true"
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["get", "create", "patch", "watch", "list", "delete"]
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
apiVersion: capsule.clastix.io/v1beta2
|
||||
kind: GlobalTenantResource
|
||||
metadata:
|
||||
name: custom-cm
|
||||
spec:
|
||||
resyncPeriod: 60s
|
||||
resources:
|
||||
- additionalMetadata:
|
||||
labels:
|
||||
"replicated-by": "capsule"
|
||||
rawItems:
|
||||
- apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: game-demo
|
||||
data:
|
||||
# property-like keys; each key maps to a simple value
|
||||
player_initial_lives: "3"
|
||||
ui_properties_file_name: "user-interface.properties"
|
||||
---
|
||||
apiVersion: capsule.clastix.io/v1beta2
|
||||
kind: GlobalTenantResource
|
||||
metadata:
|
||||
name: gitops-owners
|
||||
spec:
|
||||
resyncPeriod: 60s
|
||||
resources:
|
||||
- additionalMetadata:
|
||||
labels:
|
||||
"replicated-by": "capsule"
|
||||
rawItems:
|
||||
- apiVersion: capsule.clastix.io/v1beta2
|
||||
kind: TenantOwner
|
||||
metadata:
|
||||
name: "{{tenant.name}}-{{namespace}}"
|
||||
spec:
|
||||
clusterRoles:
|
||||
- capsule-namespace-deleter
|
||||
- admin
|
||||
kind: ServiceAccount
|
||||
name: "system:serviceaccount:{{namespace}}:gitops-reconciler"
|
||||
@@ -2,20 +2,45 @@
|
||||
apiVersion: capsule.clastix.io/v1beta2
|
||||
kind: GlobalTenantResource
|
||||
metadata:
|
||||
name: custom-cm
|
||||
namespace: solar-system
|
||||
name: gitops-owners
|
||||
spec:
|
||||
resyncPeriod: 60s
|
||||
dependsOn:
|
||||
- name: custom-cm-2
|
||||
resources:
|
||||
- additionalMetadata:
|
||||
labels:
|
||||
"replicated-by": "capsule"
|
||||
rawItems:
|
||||
- apiVersion: v1
|
||||
kind: ConfigMap
|
||||
- apiVersion: capsule.clastix.io/v1beta2
|
||||
kind: TenantOwner
|
||||
metadata:
|
||||
name: game-demo
|
||||
data:
|
||||
# property-like keys; each key maps to a simple value
|
||||
player_initial_lives: "3"
|
||||
ui_properties_file_name: "user-interface.properties"
|
||||
name: "{{tenant.name}}-{{namespace}}"
|
||||
spec:
|
||||
clusterRoles:
|
||||
- capsule-namespace-deleter
|
||||
- admin
|
||||
kind: ServiceAccount
|
||||
name: "system:serviceaccount:{{namespace}}:gitops-reconciler"
|
||||
---
|
||||
apiVersion: capsule.clastix.io/v1beta2
|
||||
kind: GlobalTenantResource
|
||||
metadata:
|
||||
name: cluster-replication
|
||||
spec:
|
||||
resyncPeriod: 60s
|
||||
scope: None
|
||||
resources:
|
||||
- generators:
|
||||
- template: |
|
||||
{{ $$key := generateAgeKey }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: "cluster-replication"
|
||||
namespace: "default"
|
||||
data:
|
||||
data: |
|
||||
identity: {{ $$key.Identity | quote }}
|
||||
recipient: {{ $$key.Recipient | quote }}
|
||||
|
||||
@@ -9,6 +9,31 @@ spec:
|
||||
owners:
|
||||
- name: alice
|
||||
kind: User
|
||||
rules:
|
||||
- permissions:
|
||||
rules:
|
||||
- clusterRoles:
|
||||
- "configmap-replicator"
|
||||
- namespaceSelector:
|
||||
matchExpressions:
|
||||
- key: env
|
||||
operator: In
|
||||
values:
|
||||
- "test"
|
||||
permissions:
|
||||
rules:
|
||||
- clusterRoles:
|
||||
- "secret-replicator"
|
||||
- namespaceSelector:
|
||||
matchExpressions:
|
||||
- key: env
|
||||
operator: In
|
||||
values:
|
||||
- "prod"
|
||||
permissions:
|
||||
rules:
|
||||
- clusterRoles:
|
||||
- "sade-boi"
|
||||
permissions:
|
||||
matchOwners:
|
||||
- matchLabels:
|
||||
@@ -16,9 +41,6 @@ spec:
|
||||
- matchLabels:
|
||||
tenant: solar
|
||||
namespaceOptions:
|
||||
requiredMetadata:
|
||||
labels:
|
||||
env: "prod|test|dev"
|
||||
additionalMetadata:
|
||||
labels:
|
||||
team: platform
|
||||
@@ -33,6 +55,16 @@ spec:
|
||||
- apiGroup: rbac.authorization.k8s.io
|
||||
kind: User
|
||||
name: joe
|
||||
resourceQuotas:
|
||||
scope: Tenant
|
||||
items:
|
||||
- hard:
|
||||
limits.cpu: "8"
|
||||
limits.memory: 16Gi
|
||||
requests.cpu: "8"
|
||||
requests.memory: 16Gi
|
||||
- hard:
|
||||
pods: "10"
|
||||
---
|
||||
apiVersion: capsule.clastix.io/v1beta2
|
||||
kind: Tenant
|
||||
@@ -41,10 +73,6 @@ metadata:
|
||||
labels:
|
||||
customer: a
|
||||
spec:
|
||||
namespaceOptions:
|
||||
requiredMetadata:
|
||||
labels:
|
||||
env: "prod|test|dev"
|
||||
permissions:
|
||||
matchOwners:
|
||||
- matchLabels:
|
||||
@@ -66,6 +94,12 @@ spec:
|
||||
- url: "harbor/.*"
|
||||
policy:
|
||||
- "Never"
|
||||
- enforce:
|
||||
registries:
|
||||
- url: "custom/.*"
|
||||
policy:
|
||||
- "Never"
|
||||
|
||||
- namespaceSelector:
|
||||
matchExpressions:
|
||||
- key: env
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/flux2/releases/download/v2.4.0/install.yaml
|
||||
- https://github.com/fluxcd/flux2/releases/download/v2.7.5/install.yaml
|
||||
patches:
|
||||
- patch: |
|
||||
- op: add
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
CLUSTER_NAME="${1:-capsule}"
|
||||
NAMESPACE="${2:-capsule-system}"
|
||||
SA_NAME="${3:-capsule}"
|
||||
TARGET="${4:-kubeconfig-${SA_NAME}.yaml}"
|
||||
|
||||
SECRET_NAME="${SA_NAME}-static-token"
|
||||
|
||||
echo "👉 Using cluster: $CLUSTER_NAME"
|
||||
echo "👉 Namespace: $NAMESPACE"
|
||||
echo "👉 ServiceAccount: $SA_NAME"
|
||||
echo "👉 Target: $TARGET"
|
||||
|
||||
echo "📄 Exporting kubeconfig..."
|
||||
TMP_KUBECONFIG=$(mktemp)
|
||||
kind get kubeconfig --name "$CLUSTER_NAME" > "$TMP_KUBECONFIG"
|
||||
|
||||
echo "🔐 Creating static token secret..."
|
||||
|
||||
kubectl -n "$NAMESPACE" apply -f - <<EOF
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: ${SECRET_NAME}
|
||||
annotations:
|
||||
kubernetes.io/service-account.name: ${SA_NAME}
|
||||
type: kubernetes.io/service-account-token
|
||||
EOF
|
||||
|
||||
echo "⏳ Waiting for token to populate..."
|
||||
sleep 2
|
||||
|
||||
TOKEN=$(kubectl -n "$NAMESPACE" get secret "$SECRET_NAME" \
|
||||
-o jsonpath='{.data.token}' | base64 -d)
|
||||
|
||||
SERVER=$(kubectl config view --raw --kubeconfig "$TMP_KUBECONFIG" \
|
||||
-o jsonpath='{.clusters[0].cluster.server}')
|
||||
|
||||
CA_DATA=$(kubectl config view --raw --kubeconfig "$TMP_KUBECONFIG" \
|
||||
-o jsonpath='{.clusters[0].cluster.certificate-authority-data}')
|
||||
|
||||
mkdir -p "$(dirname "$TARGET")"
|
||||
|
||||
cat > "$TARGET" <<EOF
|
||||
apiVersion: v1
|
||||
kind: Config
|
||||
clusters:
|
||||
- name: kind
|
||||
cluster:
|
||||
certificate-authority-data: ${CA_DATA}
|
||||
server: ${SERVER}
|
||||
contexts:
|
||||
- name: ${SA_NAME}-context
|
||||
context:
|
||||
cluster: kind
|
||||
namespace: ${NAMESPACE}
|
||||
user: ${SA_NAME}
|
||||
current-context: ${SA_NAME}-context
|
||||
users:
|
||||
- name: ${SA_NAME}
|
||||
user:
|
||||
token: ${TOKEN}
|
||||
EOF
|
||||
|
||||
rm -f "$TMP_KUBECONFIG"
|
||||
|
||||
echo "✅ Done!"
|
||||
echo "👉 SA kubeconfig written to: $TARGET"
|
||||
echo
|
||||
echo "export SERVICE_ACCOUNT=$SA_NAME"
|
||||
echo "export NAMESPACE=$NAMESPACE"
|
||||
echo "export KUBECONFIG=$TARGET"
|
||||
Reference in New Issue
Block a user