add user-controller webhook (#1766)

* feature(main): delete api logic

Signed-off-by: cuisongliu <cuisongliu@qq.com>

* feature(main): add user controller webhook

Signed-off-by: cuisongliu <cuisongliu@qq.com>

Signed-off-by: cuisongliu <cuisongliu@qq.com>
This commit is contained in:
cuisongliu
2022-09-19 20:40:44 +08:00
committed by GitHub
parent 5b781cc7a1
commit d58fa977df
30 changed files with 1488 additions and 251 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
# Image URL to use all building/pushing image targets
IMG ?= ghcr.io/labring/user-controller:dev
IMG ?= ghcr.io/labring/user-controller:dev
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.24.1
@@ -99,7 +99,7 @@ deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in
.PHONY: deploy
pre-deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default > deploy/manifests/deploy.yaml
$(KUSTOMIZE) build -e SERVICE_NAME=webhook-service -e SERVICE_NAMESPACE=system config/default > deploy/manifests/deploy.yaml
.PHONY: undeploy
undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
+13 -13
View File
@@ -6,40 +6,40 @@ repo: github.com/labring/sealos/controllers/user
resources:
- api:
crdVersion: v1
namespaced: true
controller: true
domain: sealos.io
group: user
kind: User
path: github.com/labring/sealos/controllers/user/api/v1
version: v1
webhooks:
defaulting: true
validation: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: sealos.io
group: user
kind: UserGroupUserBinding
kind: UserGroup
path: github.com/labring/sealos/controllers/user/api/v1
version: v1
webhooks:
defaulting: true
validation: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: sealos.io
group: user
kind: UserGroupNamespaceBinding
path: github.com/labring/sealos/controllers/user/api/v1
version: v1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: sealos.io
group: user
kind: UserGroupBinding
path: github.com/labring/sealos/controllers/user/api/v1
version: v1
webhooks:
defaulting: true
validation: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
+260
View File
@@ -212,3 +212,263 @@ subject:
name: f8699ded-58d3-432b-a9ff-56568b57a38d
userGroupRef: ug-f8699ded-58d3-432b-a9ff-56568b57a38d
```
# add webhook
```go
const (
UserAnnotationOwnerKey = "user.sealos.io/creator"
UserAnnotationDisplayKey = "user.sealos.io/display-name"
)
const (
UgNameLabelKey = "user.sealos.io/usergroup.name"
UgRoleLabelKey = "user.sealos.io/usergroup.role"
UgBindingKindLabelKey = "user.sealos.io/usergroupbinding.kind"
UgBindingNameLabelKey = "user.sealos.io/usergroupbinding.name"
)
```
```yaml
apiVersion: v1
items:
- apiVersion: user.sealos.io/v1
kind: User
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"user.sealos.io/v1","kind":"User","metadata":{"annotations":{},"name":"f8699ded-58d3-432b-a9ff-56568b57a38d"},"spec":{"csrExpirationSeconds":1000000000}}
user.sealos.io/display-name: f8699ded-58d3-432b-a9ff-56568b57a38d
creationTimestamp: "2022-09-14T14:52:02Z"
finalizers:
- sealos.io/user.finalizers
generation: 1
name: f8699ded-58d3-432b-a9ff-56568b57a38d
resourceVersion: "416042"
uid: 48a7d9e6-5d15-4b26-923c-667d7b8c429f
spec:
csrExpirationSeconds: 1000000000
status:
conditions:
- lastHeartbeatTime: "2022-09-14T14:52:00Z"
lastTransitionTime: "2022-09-14T14:52:00Z"
message: user has been initialized
reason: Initialized
status: "True"
type: Initialized
- lastHeartbeatTime: "2022-09-14T14:52:00Z"
lastTransitionTime: "2022-09-14T14:52:00Z"
message: sync kube config successfully
reason: Ready
status: "True"
type: KubeConfigSyncReady
- lastHeartbeatTime: "2022-09-14T14:52:00Z"
lastTransitionTime: "2022-09-14T14:52:00Z"
message: sync owner ug successfully
reason: Ready
status: "True"
type: OwnerUGSyncReady
- lastHeartbeatTime: "2022-09-14T14:52:00Z"
lastTransitionTime: "2022-09-14T14:52:00Z"
message: sync owner ug namespace binding successfully
reason: Ready
status: "True"
type: OwnerUGNamespaceBindingSyncReady
- lastHeartbeatTime: "2022-09-14T14:52:00Z"
lastTransitionTime: "2022-09-14T14:52:00Z"
message: User is available now
reason: Ready
status: "True"
type: Ready
kubeConfig: |
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM2VENDQWRHZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQ0FYRFRJeU1Ea3hOREExTlRRMU5Wb1lEekl4TWpJd09ESXhNRFUxTkRVMVdqQVZNUk13RVFZRApWUVFERXdwcmRXSmxjbTVsZEdWek1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBCjBMSndEbndvYzV2YittMkpadVplMnB3dkhWZHpyY21SRkdIaUVmQzg4L2hscjVDWllMSkZkNVc5WjRjUFU1VjMKY1NVNG8wL1J1bmNiclNpNmZrdTNFZ0lya1Z0UUkxUm5Ub3ExTUNFeXk1Q3ZvRlpETkMwSW5wRTY2Nng2S0xpagpRZTFyRXYrYmxZc3B4MnE4Tmhtek1zZWR3ZzZod1ErM2RoQ0U5ck9Vb3UwRHZwQ2VKVjAwazkweVRmZGNTN1c0CnJCbFZ1dUhtNVlVU1M3SEZubTBFMUZQd0RONXhNaG9vZmkyVGE3eTZPNzlBZTl5cDZDZlV4cFRra28vOGNwZUIKKzI3NzRNelYyZmJ4Yys0Ri9McWpRTms2VVpIOTlTT3gvTUZJLzFCZWVqeTA1OGdtQ2U3QUlkbEpCdnFQOWRXbwp0cEtlb1ZyN3Fkc0owSEhTeUhmaVNRSURBUUFCbzBJd1FEQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUCkFRSC9CQVV3QXdFQi96QWRCZ05WSFE0RUZnUVVlOW9SQmQ2UVBjNk1VNjcyQjAwOU9nR2VtVjB3RFFZSktvWkkKaHZjTkFRRUxCUUFEZ2dFQkFEYkVDMk9oWkpiUzZldUZmTFNEdG11VlNoc3dFbDRlMFBsWWhnYTBKRHlQSDBUZQpCNmdPWVhZSndrZWxhTWxTUTFFY3ZVa3FHWlhqVUw4Qnl4YzJ0K0pxUDYzQ3ZtZHVzY0NHcWQzTDZTY21UQmZvCjhhbmpENmtoSDZBaHNPVnVsODFYcU9iV2Zxd0diTytGZFgvQi81TDB4bUQ0WUtnNE9iMzdlMWxXb2xJbEJZWmYKMEhqZGNMNjFyYytyWEloeGFPMmlzWHJiSmxzQ0hwTERoVkVKM2o0cjJWdkJFbjRMYWxlZmlYdVdrU3M4RmF0Nwo3N1hwSmhIblA5SHlma0Z1UERsRmpyN1FpcE9wRnJKUXBaeHhmSmREVEhFWUpRV3V0ZytqZjhVZzQweGg5ZS9GCnBNdDlNcTVKSGt3YWVPOEhpSmhaN2dxNjJBQTdseVp4TzBDbnhUYz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
server: https://192.168.64.29:6443
name: sealos
contexts:
- context:
cluster: sealos
user: f8699ded-58d3-432b-a9ff-56568b57a38d
name: f8699ded-58d3-432b-a9ff-56568b57a38d@sealos
current-context: f8699ded-58d3-432b-a9ff-56568b57a38d@sealos
kind: Config
preferences: {}
users:
- name: f8699ded-58d3-432b-a9ff-56568b57a38d
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lSQU9SY1E5Nnc5UHh6MjBTQXNOKzVoa1V3RFFZSktvWklodmNOQVFFTEJRQXcKRlRFVE1CRUdBMVVFQXhNS2EzVmlaWEp1WlhSbGN6QWdGdzB5TWpBNU1UUXhORFEzTURKYUdBOHlNRFUwTURVeQpNekUyTXpNME1sb3dMekV0TUNzR0ExVUVBeE1rWmpnMk9UbGtaV1F0TlRoa015MDBNekppTFdFNVptWXROVFkxCk5qaGlOVGRoTXpoa01JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMnB4VHVwNHUKR0xzeVQ1a1RBeldrZGlTSUtnY09OTTkxU3FLV25CM2t1ektaKzUvWkdiT1MrWElGV3IrbEdtbkZnMUY0Sng5Ywpvb3I0K09KTnBSWHdpNElkejgvRVllbGU0cmU1bjE3enlvUHFLWFBGemdjM1pOc2d0Ni9WQm5ENVBYaUlvc3pECnI0dC9RQWh3SFA0VjVyTkIrTUJHbjdtMzJaY1UxNTlFak5sOVJjQWhNZHJWKzAvRVZNN1ZGVThVVnhzZWV1c1QKQlBvTDJOanZwek1NY0VTeFpsY3lVS1lpNG5TamtXR3ZOSnZja1BDaTFHaUhUc1lZZE1qKzRFQTZmZnRKRC9IYwprMkVCWVVVQmlWeXRtVUNRSEZIWm5rU0Eva1FwUFpHVll0Y1VTaDB1bmY4cWwyM2k1RUVsL3M1eTRjSmI0SVdmCmY3anpaWk9uTmpBVlVRSURBUUFCbzFZd1ZEQU9CZ05WSFE4QkFmOEVCQU1DQmFBd0V3WURWUjBsQkF3d0NnWUkKS3dZQkJRVUhBd0l3REFZRFZSMFRBUUgvQkFJd0FEQWZCZ05WSFNNRUdEQVdnQlI3MmhFRjNwQTl6b3hUcnZZSApUVDA2QVo2WlhUQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFGdHNUOFlaS1dNelEydUIzZVZqeVVaRXM5dEY4Cms3MXk4YVZIV2owcEVFSTgzUlpSUjNMbzg5V3l4a3p6c0N2NjZYSkdKVHRzWFlYdTVjL1FpZ3NHemhGRTB0WlAKeGRIc3Y4SzRVelZablhSc2Y5U3BWcmNTQnR6WHEveEw5bXJ4VCtLcklBTEEzYUxQTUpsRGs2bnNuNnlRc0J2egpvWHBJbWlkblVnQWNydmxMSFFSMTRaSHU3dEFaVmh5blFJTGNJRjhaUnpvYnhpclNPM0ZVUkhpMFZPaHRWMUpaCi93NzhwNVhWZ3NYT2ozUmliWm9qUkdUT2w1b0xlUHBaT0xueHZoYkNaMjBmV2FBaHliMlhNSzZiQmR6ckZUbWUKR2VPdGFUWEt2UTE3cXJZTjVKVTVKQ0JhaWFRbjEyZjA1c3E2U0NtUVJVRWxpVmQ1VERiNS9ydVpZUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBMnB4VHVwNHVHTHN5VDVrVEF6V2tkaVNJS2djT05NOTFTcUtXbkIza3V6S1orNS9aCkdiT1MrWElGV3IrbEdtbkZnMUY0Sng5Y29vcjQrT0pOcFJYd2k0SWR6OC9FWWVsZTRyZTVuMTd6eW9QcUtYUEYKemdjM1pOc2d0Ni9WQm5ENVBYaUlvc3pEcjR0L1FBaHdIUDRWNXJOQitNQkduN20zMlpjVTE1OUVqTmw5UmNBaApNZHJWKzAvRVZNN1ZGVThVVnhzZWV1c1RCUG9MMk5qdnB6TU1jRVN4WmxjeVVLWWk0blNqa1dHdk5KdmNrUENpCjFHaUhUc1lZZE1qKzRFQTZmZnRKRC9IY2syRUJZVVVCaVZ5dG1VQ1FIRkhabmtTQS9rUXBQWkdWWXRjVVNoMHUKbmY4cWwyM2k1RUVsL3M1eTRjSmI0SVdmZjdqelpaT25OakFWVVFJREFRQUJBb0lCQUVGYkpTa1FxMFZYaWNZRQpSSXZjR0t2OVpmdnltZ3V0emlvZkM1bm0wZ0FwTTZIbmV4ZFUrV2E3OE4vZGxiV2MwNkRiMVdrVTFqUCtDa3NXCkZSSjZ5YXhiblNBSXhIUmxPYW5jTlpGdzZMK3R5bTdVSHRubWpHZ0pudkZyanV0YkVSaVFsWURlYU01dGpRQ08KeFQzVnRLU0JDUU1lTUw4RjNmSWVXZXZRd01TK24wUU5TVnQ4R1lLblptVDVJaUQyU2FtcUFLQW1vRW9kc09GRwpDR3JoUm5jL2MydVJGQzhwdms0aFZCWURSTEV1VGhNU3gvY1JRbjhTdTJKaktCNWRndnZXVHVxL3NJSjQzOWwrCncxWUpSZTMreWlXVTF5Y3lCNm5aOG5hT0RRc1RpTnVudkpQd2tvYUF3U3RxZzVYTGtXTXBiUVFKVWo5ZktzaHgKVURpdThVRUNnWUVBOW4xTkE1d0M0clE1RnVQMHZxMXdZKzNsaitSSzZBT0ZVd085VkN0S2FXUGZqT1JsaWxQNwpmSTFpUUc2V2MxbG9kTHVDVjFQZm9icmFyZ3p0M0hJV213dlpnMVRLTldZTVNwTGMzMUhnN0FlMkU2bHZGNnloCmFweU9saDdIRU1NV3Aybm55d0FaSWdWM1EyUWdUNHVIY1lYU3ZpbCtqQmVWZUQ4NzlJM1dXVmtDZ1lFQTR3dW4KUk80QmwyTjByNXJhRXJoTVRjT2QwYXFxV29lYWpEMHhIaXVTRWlRTytqYU1HU2theWNURzQ4UGc3Vk1LaTVPNQpiN1dydVJ3NFVNVFRaK3ZGRTRURjdDR0lBcmJ2bEhPRExxaDRJeWQyY1BJcEtQc2xpZ1F3VDhKUkt0VmtoVXNoCnpPRTgreHgvVXBzQ1NpVU14S3Z0aGZFcW5IK0ZhR3NiYW85aEpMa0NnWUVBcDA2OXE2bUZ1K09nckl6bVgxYlMKWnNIZmhCL3RTRGE3bEhHQlhWUlZHZHdVclVtS01xNTJrVUJXWkcycjZYZlNrd21EbTBydkRKUU1Rdis3cEZvOApSZGx4TnRlaXVVUWZLNjhzQk5sSzFtc1ZoNXNHTVFlWU9Ra3pMMnFNckMvL2ZIdENQbVErcXYwU3lzZDN0d1o2ClZQQUU3OWF5Y3R5L00vT1grcE1iMzJFQ2dZQkRhcjVzVlUvYnFBaUo3QzA4eWNTK2dvdG1Lb3NTL3BrQmMxb1cKWDFHc1dWQ3BNM0UrTjFwZzl6RW5pSTVOYWc4RGl3WFJDZHpIeG4xaVhrOTMyQ1pZdVdBYjBZa1ZaVVNXakFZego0SXByeGRnQmlhWjNLTHZvMDMyVThWb3dvZFNMVDlmbGdpd2RWRVRxUG1UYnAweTNTV1hxRThaWFdmWS9IeTZ3CjRZb3k0UUtCZ0ZvYmJHdVBhQ0QwT044dmk3TnhGZStzbGNEWlBOTWgydXRZRWFwQnpsTkNDNFB2eXFuTjlTdDgKLzhJSmRVc0M3MVNJYU4zZWJWQmUzKzdieFk0MzVwN0hEVXlGdkRQbTJnOHUvelVPbHU5SzNjZXVQRExJcDVoOAp1MG9oaHFFZUN5cHRFcDFBM1hTNGFRaVlsb3NUTkxrenlKRXM5cnh0aWdHT3ZoOXZKVjRtCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
observedCSRExpirationSeconds: 1000000000
observedGeneration: 1
phase: Active
- apiVersion: user.sealos.io/v1
kind: UserGroup
metadata:
annotations:
user.sealos.io/creator: f8699ded-58d3-432b-a9ff-56568b57a38d
user.sealos.io/display-name: ug-f8699ded-58d3-432b-a9ff-56568b57a38d
creationTimestamp: "2022-09-14T14:52:02Z"
finalizers:
- sealos.io/user.group.finalizers
generation: 1
name: ug-f8699ded-58d3-432b-a9ff-56568b57a38d
ownerReferences:
- apiVersion: user.sealos.io/v1
blockOwnerDeletion: true
controller: true
kind: User
name: f8699ded-58d3-432b-a9ff-56568b57a38d
uid: 48a7d9e6-5d15-4b26-923c-667d7b8c429f
resourceVersion: "416046"
uid: c0b1faf8-3cc4-4817-bd28-e508eb3ab0f4
status:
conditions:
- lastHeartbeatTime: "2022-09-14T14:52:00Z"
lastTransitionTime: "2022-09-14T14:52:00Z"
message: user group has been initialized
reason: Initialized
status: "True"
type: Initialized
- lastHeartbeatTime: "2022-09-14T14:52:00Z"
lastTransitionTime: "2022-09-14T14:52:00Z"
message: sync owner ug user binding successfully
reason: Ready
status: "True"
type: OwnerUGUserBindingSyncReady
- lastHeartbeatTime: "2022-09-14T14:52:00Z"
lastTransitionTime: "2022-09-14T14:52:00Z"
message: UserGroup is available now
reason: Ready
status: "True"
type: Ready
observedGeneration: 1
phase: Active
- apiVersion: user.sealos.io/v1
kind: UserGroupBinding
metadata:
annotations:
user.sealos.io/creator: f8699ded-58d3-432b-a9ff-56568b57a38d
creationTimestamp: "2022-09-14T14:52:02Z"
finalizers:
- sealos.io/user.group.binding.finalizers
generation: 1
labels:
user.sealos.io/usergroup.name: ug-f8699ded-58d3-432b-a9ff-56568b57a38d
user.sealos.io/usergroup.role: user
user.sealos.io/usergroupbinding.kind: namespace
user.sealos.io/usergroupbinding.name: ns-f8699ded-58d3-432b-a9ff-56568b57a38d
name: ugn-f8699ded-58d3-432b-a9ff-56568b57a38d
ownerReferences:
- apiVersion: user.sealos.io/v1
blockOwnerDeletion: true
controller: true
kind: User
name: f8699ded-58d3-432b-a9ff-56568b57a38d
uid: 48a7d9e6-5d15-4b26-923c-667d7b8c429f
resourceVersion: "422287"
uid: 3ac62863-d9a1-4159-bc45-fe4c71d691de
roleRef: user
status:
conditions:
- lastHeartbeatTime: "2022-09-14T14:52:00Z"
lastTransitionTime: "2022-09-14T14:52:00Z"
message: user group binding has been initialized
reason: Initialized
status: "True"
type: Initialized
- lastHeartbeatTime: "2022-09-14T14:52:00Z"
lastTransitionTime: "2022-09-14T14:52:00Z"
message: sync ug namespace successfully
reason: Ready
status: "True"
type: UGNamespaceSyncReady
- lastHeartbeatTime: "2022-09-14T14:52:00Z"
lastTransitionTime: "2022-09-14T14:52:00Z"
message: sync ug namespace binding successfully
reason: Ready
status: "True"
type: UGNamespaceBindingSyncReady
- lastHeartbeatTime: "2022-09-14T14:52:00Z"
lastTransitionTime: "2022-09-14T14:52:00Z"
message: UserGroupBinding is available now
reason: Ready
status: "True"
type: Ready
observedGeneration: 1
phase: Active
subject:
kind: Namespace
name: ns-f8699ded-58d3-432b-a9ff-56568b57a38d
userGroupRef: ug-f8699ded-58d3-432b-a9ff-56568b57a38d
- apiVersion: user.sealos.io/v1
kind: UserGroupBinding
metadata:
annotations:
user.sealos.io/creator: f8699ded-58d3-432b-a9ff-56568b57a38d
creationTimestamp: "2022-09-14T14:52:02Z"
finalizers:
- sealos.io/user.group.binding.finalizers
generation: 1
labels:
user.sealos.io/usergroup.name: ug-f8699ded-58d3-432b-a9ff-56568b57a38d
user.sealos.io/usergroup.role: user
user.sealos.io/usergroupbinding.kind: user
user.sealos.io/usergroupbinding.name: f8699ded-58d3-432b-a9ff-56568b57a38d
name: ugu-f8699ded-58d3-432b-a9ff-56568b57a38d
ownerReferences:
- apiVersion: user.sealos.io/v1
blockOwnerDeletion: true
controller: true
kind: UserGroup
name: ug-f8699ded-58d3-432b-a9ff-56568b57a38d
uid: c0b1faf8-3cc4-4817-bd28-e508eb3ab0f4
resourceVersion: "419386"
uid: b6cbea8a-a248-4bb1-a9ae-30ba39db072f
roleRef: user
status:
conditions:
- lastHeartbeatTime: "2022-09-14T14:52:00Z"
lastTransitionTime: "2022-09-14T14:52:00Z"
message: user group binding has been initialized
reason: Initialized
status: "True"
type: Initialized
- lastHeartbeatTime: "2022-09-14T14:52:00Z"
lastTransitionTime: "2022-09-14T14:52:00Z"
message: sync ug user binding by owner successfully
reason: Ready
status: "True"
type: UGUserBindingSyncReadyByOwner
- lastHeartbeatTime: "2022-09-14T14:52:00Z"
lastTransitionTime: "2022-09-14T14:52:00Z"
message: sync ug user binding successfully
reason: Ready
status: "True"
type: UGUserBindingSyncReady
- lastHeartbeatTime: "2022-09-14T14:52:00Z"
lastTransitionTime: "2022-09-14T14:52:00Z"
message: sync ug namespace binding successfully
reason: Ready
status: "True"
type: UGNamespaceBindingSyncReady
- lastHeartbeatTime: "2022-09-14T14:52:00Z"
lastTransitionTime: "2022-09-14T14:52:00Z"
message: UserGroupBinding is available now
reason: Ready
status: "True"
type: Ready
observedGeneration: 1
phase: Active
subject:
apiGroup: user.sealos.io
kind: User
name: f8699ded-58d3-432b-a9ff-56568b57a38d
userGroupRef: ug-f8699ded-58d3-432b-a9ff-56568b57a38d
kind: List
metadata:
resourceVersion: ""
```
@@ -20,6 +20,9 @@ limitations under the License.
package v1
import (
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
)
@@ -34,3 +37,39 @@ var (
// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)
const (
UserAnnotationOwnerKey = "user.sealos.io/creator"
UserAnnotationDisplayKey = "user.sealos.io/display-name"
)
const (
UgNameLabelKey = "user.sealos.io/usergroup.name"
UgRoleLabelKey = "user.sealos.io/usergroup.role"
UgBindingKindLabelKey = "user.sealos.io/usergroupbinding.kind"
UgBindingNameLabelKey = "user.sealos.io/usergroupbinding.name"
)
func validateAnnotationKeyNotEmpty(meta metav1.ObjectMeta, key string) error {
if meta.Annotations[key] == "" {
return fmt.Errorf("annotation %s not allow empty", key)
}
return nil
}
func validateLabelKeyNotEmpty(meta metav1.ObjectMeta, key string) error {
if meta.Labels[key] == "" {
return fmt.Errorf("label %s not allow empty", key)
}
return nil
}
func initAnnotationAndLabels(meta metav1.ObjectMeta) metav1.ObjectMeta {
if meta.Annotations == nil {
meta.Annotations = make(map[string]string, 0)
}
if meta.Labels == nil {
meta.Labels = make(map[string]string, 0)
}
return meta
}
+9
View File
@@ -17,6 +17,8 @@ limitations under the License.
package v1
import (
"errors"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@@ -115,3 +117,10 @@ type UserList struct {
func init() {
SchemeBuilder.Register(&User{}, &UserList{})
}
func (r *User) validateCSRExpirationSeconds() error {
if r.Spec.CSRExpirationSeconds == 0 {
return errors.New("CSRExpirationSeconds is not allowed to be 0")
}
return nil
}
+86
View File
@@ -0,0 +1,86 @@
/*
Copyright 2022 labring.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1
import (
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
)
// log is for logging in this package.
var userlog = logf.Log.WithName("user-resource")
func (r *User) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
Complete()
}
// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
//+kubebuilder:webhook:path=/mutate-user-sealos-io-v1-user,mutating=true,failurePolicy=fail,sideEffects=None,groups=user.sealos.io,resources=users,verbs=create;update,versions=v1,name=muser.kb.io,admissionReviewVersions=v1
var _ webhook.Defaulter = &User{}
// Default implements webhook.Defaulter so a webhook will be registered for the type
func (r *User) Default() {
userlog.Info("default", "name", r.Name)
r.ObjectMeta = initAnnotationAndLabels(r.ObjectMeta)
if r.Spec.CSRExpirationSeconds == 0 {
r.Spec.CSRExpirationSeconds = 7200
}
if r.Annotations[UserAnnotationDisplayKey] == "" {
r.Annotations[UserAnnotationDisplayKey] = r.Name
}
}
// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
//+kubebuilder:webhook:path=/validate-user-sealos-io-v1-user,mutating=false,failurePolicy=fail,sideEffects=None,groups=user.sealos.io,resources=users,verbs=create;update,versions=v1,name=vuser.kb.io,admissionReviewVersions=v1
var _ webhook.Validator = &User{}
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *User) ValidateCreate() error {
userlog.Info("validate create", "name", r.Name)
if err := r.validateCSRExpirationSeconds(); err != nil {
return err
}
if err := validateAnnotationKeyNotEmpty(r.ObjectMeta, UserAnnotationDisplayKey); err != nil {
return err
}
return nil
}
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (r *User) ValidateUpdate(old runtime.Object) error {
userlog.Info("validate update", "name", r.Name)
if err := r.validateCSRExpirationSeconds(); err != nil {
return err
}
if err := validateAnnotationKeyNotEmpty(r.ObjectMeta, UserAnnotationDisplayKey); err != nil {
return err
}
return nil
}
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (r *User) ValidateDelete() error {
userlog.Info("validate delete", "name", r.Name)
return nil
}
@@ -0,0 +1,85 @@
/*
Copyright 2022 labring.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1
import (
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
)
// log is for logging in this package.
var usergrouplog = logf.Log.WithName("usergroup-resource")
func (r *UserGroup) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
Complete()
}
// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
//+kubebuilder:webhook:path=/mutate-user-sealos-io-v1-usergroup,mutating=true,failurePolicy=fail,sideEffects=None,groups=user.sealos.io,resources=usergroups,verbs=create;update,versions=v1,name=musergroup.kb.io,admissionReviewVersions=v1
var _ webhook.Defaulter = &UserGroup{}
// Default implements webhook.Defaulter so a webhook will be registered for the type
func (r *UserGroup) Default() {
usergrouplog.Info("default", "name", r.Name)
r.ObjectMeta = initAnnotationAndLabels(r.ObjectMeta)
if r.Annotations[UserAnnotationDisplayKey] == "" {
r.Annotations[UserAnnotationDisplayKey] = r.Name
}
}
// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
//+kubebuilder:webhook:path=/validate-user-sealos-io-v1-usergroup,mutating=false,failurePolicy=fail,sideEffects=None,groups=user.sealos.io,resources=usergroups,verbs=create;update,versions=v1,name=vusergroup.kb.io,admissionReviewVersions=v1
var _ webhook.Validator = &UserGroup{}
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *UserGroup) ValidateCreate() error {
usergrouplog.Info("validate create", "name", r.Name)
if err := validateAnnotationKeyNotEmpty(r.ObjectMeta, UserAnnotationDisplayKey); err != nil {
return err
}
if err := validateAnnotationKeyNotEmpty(r.ObjectMeta, UserAnnotationOwnerKey); err != nil {
return err
}
return nil
}
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (r *UserGroup) ValidateUpdate(old runtime.Object) error {
usergrouplog.Info("validate update", "name", r.Name)
if err := validateAnnotationKeyNotEmpty(r.ObjectMeta, UserAnnotationDisplayKey); err != nil {
return err
}
if err := validateAnnotationKeyNotEmpty(r.ObjectMeta, UserAnnotationOwnerKey); err != nil {
return err
}
return nil
}
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (r *UserGroup) ValidateDelete() error {
usergrouplog.Info("validate delete", "name", r.Name)
// TODO(user): fill in your validation logic upon object deletion.
return nil
}
@@ -0,0 +1,121 @@
/*
Copyright 2022 labring.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1
import (
"strings"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
)
// log is for logging in this package.
var usergroupbindinglog = logf.Log.WithName("usergroupbinding-resource")
func (r *UserGroupBinding) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
Complete()
}
// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
//+kubebuilder:webhook:path=/mutate-user-sealos-io-v1-usergroupbinding,mutating=true,failurePolicy=fail,sideEffects=None,groups=user.sealos.io,resources=usergroupbindings,verbs=create;update,versions=v1,name=musergroupbinding.kb.io,admissionReviewVersions=v1
var _ webhook.Defaulter = &UserGroupBinding{}
// Default implements webhook.Defaulter so a webhook will be registered for the type
func (r *UserGroupBinding) Default() {
usergroupbindinglog.Info("default", "name", r.Name)
r.ObjectMeta = initAnnotationAndLabels(r.ObjectMeta)
if r.RoleRef == "" {
r.RoleRef = RoleRefTypeUser
}
r.Labels[UgNameLabelKey] = r.UserGroupRef
r.Labels[UgRoleLabelKey] = string(r.RoleRef)
r.Labels[UgBindingKindLabelKey] = strings.ToLower(r.Subject.Kind)
r.Labels[UgBindingNameLabelKey] = strings.ToLower(r.Subject.Name)
}
// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
//+kubebuilder:webhook:path=/validate-user-sealos-io-v1-usergroupbinding,mutating=false,failurePolicy=fail,sideEffects=None,groups=user.sealos.io,resources=usergroupbindings,verbs=create;update,versions=v1,name=vusergroupbinding.kb.io,admissionReviewVersions=v1
var _ webhook.Validator = &UserGroupBinding{}
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *UserGroupBinding) ValidateCreate() error {
usergroupbindinglog.Info("validate create", "name", r.Name)
if err := r.validateWebhook(); err != nil {
return err
}
return nil
}
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (r *UserGroupBinding) ValidateUpdate(old runtime.Object) error {
usergroupbindinglog.Info("validate update", "name", r.Name)
if err := r.validateWebhook(); err != nil {
return err
}
return nil
}
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (r *UserGroupBinding) ValidateDelete() error {
usergroupbindinglog.Info("validate delete", "name", r.Name)
// TODO(user): fill in your validation logic upon object deletion.
return nil
}
func (r *UserGroupBinding) validateWebhook() error {
if err := validateAnnotationKeyNotEmpty(r.ObjectMeta, UserAnnotationOwnerKey); err != nil {
return err
}
if err := validateLabelKeyNotEmpty(r.ObjectMeta, UgNameLabelKey); err != nil {
return err
}
if err := validateLabelKeyNotEmpty(r.ObjectMeta, UgRoleLabelKey); err != nil {
return err
}
if err := validateLabelKeyNotEmpty(r.ObjectMeta, UgBindingKindLabelKey); err != nil {
return err
}
if err := validateLabelKeyNotEmpty(r.ObjectMeta, UgBindingNameLabelKey); err != nil {
return err
}
if r.RoleRef == "" {
return errors.New("roleRef is not allowed to be empty")
}
if r.UserGroupRef == "" {
return errors.New("userGroupRef not allow empty")
}
if r.Subject.Kind == "" {
return errors.New("subject.kind not allow empty")
}
if r.Subject.Name == "" {
return errors.New("subject.name not allow empty")
}
if r.Subject.APIGroup == "" && r.Subject.Kind != "Namespace" {
return errors.New("subject.name not allow empty")
}
return nil
}
@@ -0,0 +1,143 @@
/*
Copyright 2022 labring.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1
import (
"context"
"crypto/tls"
"fmt"
"net"
"path/filepath"
"testing"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
admissionv1beta1 "k8s.io/api/admission/v1beta1"
//+kubebuilder:scaffold:imports
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"
"sigs.k8s.io/controller-runtime/pkg/envtest/printer"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
)
// These tests use Ginkgo (BDD-style Go testing framework). Refer to
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
var k8sClient client.Client
var testEnv *envtest.Environment
var ctx context.Context
var cancel context.CancelFunc
func TestAPIs(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecsWithDefaultAndCustomReporters(t,
"Webhook Suite",
[]Reporter{printer.NewlineReporter{}})
}
var _ = BeforeSuite(func() {
logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)))
ctx, cancel = context.WithCancel(context.TODO())
By("bootstrapping test environment")
testEnv = &envtest.Environment{
CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")},
ErrorIfCRDPathMissing: false,
WebhookInstallOptions: envtest.WebhookInstallOptions{
Paths: []string{filepath.Join("..", "..", "config", "webhook")},
},
}
cfg, err := testEnv.Start()
Expect(err).NotTo(HaveOccurred())
Expect(cfg).NotTo(BeNil())
scheme := runtime.NewScheme()
err = AddToScheme(scheme)
Expect(err).NotTo(HaveOccurred())
err = admissionv1beta1.AddToScheme(scheme)
Expect(err).NotTo(HaveOccurred())
err = admissionv1beta1.AddToScheme(scheme)
Expect(err).NotTo(HaveOccurred())
err = admissionv1beta1.AddToScheme(scheme)
Expect(err).NotTo(HaveOccurred())
//+kubebuilder:scaffold:scheme
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme})
Expect(err).NotTo(HaveOccurred())
Expect(k8sClient).NotTo(BeNil())
// start webhook server using Manager
webhookInstallOptions := &testEnv.WebhookInstallOptions
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
Scheme: scheme,
Host: webhookInstallOptions.LocalServingHost,
Port: webhookInstallOptions.LocalServingPort,
CertDir: webhookInstallOptions.LocalServingCertDir,
LeaderElection: false,
MetricsBindAddress: "0",
})
Expect(err).NotTo(HaveOccurred())
err = (&User{}).SetupWebhookWithManager(mgr)
Expect(err).NotTo(HaveOccurred())
err = (&UserGroup{}).SetupWebhookWithManager(mgr)
Expect(err).NotTo(HaveOccurred())
err = (&UserGroupBinding{}).SetupWebhookWithManager(mgr)
Expect(err).NotTo(HaveOccurred())
//+kubebuilder:scaffold:webhook
go func() {
defer GinkgoRecover()
err = mgr.Start(ctx)
Expect(err).NotTo(HaveOccurred())
}()
// wait for the webhook server to get ready
dialer := &net.Dialer{Timeout: time.Second}
addrPort := fmt.Sprintf("%s:%d", webhookInstallOptions.LocalServingHost, webhookInstallOptions.LocalServingPort)
Eventually(func() error {
conn, err := tls.DialWithDialer(dialer, "tcp", addrPort, &tls.Config{InsecureSkipVerify: true})
if err != nil {
return err
}
conn.Close()
return nil
}).Should(Succeed())
}, 60)
var _ = AfterSuite(func() {
cancel()
By("tearing down the test environment")
err := testEnv.Stop()
Expect(err).NotTo(HaveOccurred())
})
@@ -22,7 +22,7 @@ limitations under the License.
package v1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
@@ -0,0 +1,25 @@
# The following manifests contain a self-signed issuer CR and a certificate CR.
# More document can be found at https://docs.cert-manager.io
# WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes.
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: selfsigned-issuer
namespace: system
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml
namespace: system
spec:
# $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize
dnsNames:
- $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc
- $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local
issuerRef:
kind: Issuer
name: selfsigned-issuer
secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize
@@ -0,0 +1,5 @@
resources:
- certificate.yaml
configurations:
- kustomizeconfig.yaml
@@ -0,0 +1,16 @@
# This configuration is for teaching kustomize how to update name ref and var substitution
nameReference:
- kind: Issuer
group: cert-manager.io
fieldSpecs:
- kind: Certificate
group: cert-manager.io
path: spec/issuerRef/name
varReference:
- kind: Certificate
group: cert-manager.io
path: spec/commonName
- kind: Certificate
group: cert-manager.io
path: spec/dnsNames
@@ -13,62 +13,62 @@ namePrefix: user-
# someName: someValue
bases:
- ../crd
- ../rbac
- ../manager
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
# crd/kustomization.yaml
#- ../webhook
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.
#- ../certmanager
- ../crd
- ../rbac
- ../manager
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
# crd/kustomization.yaml
- ../webhook
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.
- ../certmanager
# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
#- ../prometheus
patchesStrategicMerge:
# Protect the /metrics endpoint by putting it behind auth.
# If you want your controller-manager to expose the /metrics
# endpoint w/o any authn/z, please comment the following line.
- manager_auth_proxy_patch.yaml
# Protect the /metrics endpoint by putting it behind auth.
# If you want your controller-manager to expose the /metrics
# endpoint w/o any authn/z, please comment the following line.
- manager_auth_proxy_patch.yaml
# Mount the controller config file for loading manager configurations
# through a ComponentConfig type
#- manager_config_patch.yaml
# Mount the controller config file for loading manager configurations
# through a ComponentConfig type
#- manager_config_patch.yaml
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
# crd/kustomization.yaml
#- manager_webhook_patch.yaml
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
# crd/kustomization.yaml
- manager_webhook_patch.yaml
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'.
# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks.
# 'CERTMANAGER' needs to be enabled to use ca injection
#- webhookcainjection_patch.yaml
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'.
# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks.
# 'CERTMANAGER' needs to be enabled to use ca injection
- webhookcainjection_patch.yaml
# the following config is for teaching kustomize how to do var substitution
vars:
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix.
#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR
# objref:
# kind: Certificate
# group: cert-manager.io
# version: v1
# name: serving-cert # this name should match the one in certificate.yaml
# fieldref:
# fieldpath: metadata.namespace
#- name: CERTIFICATE_NAME
# objref:
# kind: Certificate
# group: cert-manager.io
# version: v1
# name: serving-cert # this name should match the one in certificate.yaml
#- name: SERVICE_NAMESPACE # namespace of the service
# objref:
# kind: Service
# version: v1
# name: webhook-service
# fieldref:
# fieldpath: metadata.namespace
#- name: SERVICE_NAME
# objref:
# kind: Service
# version: v1
# name: webhook-service
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix.
- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR
objref:
kind: Certificate
group: cert-manager.io
version: v1
name: serving-cert # this name should match the one in certificate.yaml
fieldref:
fieldpath: metadata.namespace
- name: CERTIFICATE_NAME
objref:
kind: Certificate
group: cert-manager.io
version: v1
name: serving-cert # this name should match the one in certificate.yaml
- name: SERVICE_NAMESPACE # namespace of the service
objref:
kind: Service
version: v1
name: webhook-service
fieldref:
fieldpath: metadata.namespace
- name: SERVICE_NAME
objref:
kind: Service
version: v1
name: webhook-service
@@ -0,0 +1,23 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: controller-manager
namespace: system
spec:
template:
spec:
containers:
- name: manager
ports:
- containerPort: 9443
name: webhook-server
protocol: TCP
volumeMounts:
- mountPath: /tmp/k8s-webhook-server/serving-certs
name: cert
readOnly: true
volumes:
- name: cert
secret:
defaultMode: 420
secretName: webhook-server-cert
@@ -0,0 +1,15 @@
# This patch add annotation to admission webhook config and
# the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize.
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: mutating-webhook-configuration
annotations:
cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: validating-webhook-configuration
annotations:
cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
+1 -16
View File
@@ -39,6 +39,7 @@ spec:
args:
- --leader-elect
image: controller:latest
imagePullPolicy: IfNotPresent
name: manager
securityContext:
allowPrivilegeEscalation: false
@@ -68,19 +69,3 @@ spec:
memory: 64Mi
serviceAccountName: controller-manager
terminationGracePeriodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
labels:
control-plane: controller-manager
name: controller-manager-api-service
namespace: system
spec:
ports:
- name: http
port: 8088
protocol: TCP
targetPort: 8088
selector:
control-plane: controller-manager
@@ -3,5 +3,4 @@ kind: User
metadata:
name: f8699ded-58d3-432b-a9ff-56568b57a38d
spec:
displayName: cuisongliu
csrExpirationSeconds: 1000000000
@@ -0,0 +1,6 @@
resources:
- manifests.yaml
- service.yaml
configurations:
- kustomizeconfig.yaml
@@ -0,0 +1,25 @@
# the following config is for teaching kustomize where to look at when substituting vars.
# It requires kustomize v2.1.0 or newer to work properly.
nameReference:
- kind: Service
version: v1
fieldSpecs:
- kind: MutatingWebhookConfiguration
group: admissionregistration.k8s.io
path: webhooks/clientConfig/service/name
- kind: ValidatingWebhookConfiguration
group: admissionregistration.k8s.io
path: webhooks/clientConfig/service/name
namespace:
- kind: MutatingWebhookConfiguration
group: admissionregistration.k8s.io
path: webhooks/clientConfig/service/namespace
create: true
- kind: ValidatingWebhookConfiguration
group: admissionregistration.k8s.io
path: webhooks/clientConfig/service/namespace
create: true
varReference:
- path: metadata/annotations
@@ -0,0 +1,134 @@
---
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
creationTimestamp: null
name: mutating-webhook-configuration
webhooks:
- admissionReviewVersions:
- v1
clientConfig:
service:
name: webhook-service
namespace: system
path: /mutate-user-sealos-io-v1-user
failurePolicy: Fail
name: muser.kb.io
rules:
- apiGroups:
- user.sealos.io
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- users
sideEffects: None
- admissionReviewVersions:
- v1
clientConfig:
service:
name: webhook-service
namespace: system
path: /mutate-user-sealos-io-v1-usergroup
failurePolicy: Fail
name: musergroup.kb.io
rules:
- apiGroups:
- user.sealos.io
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- usergroups
sideEffects: None
- admissionReviewVersions:
- v1
clientConfig:
service:
name: webhook-service
namespace: system
path: /mutate-user-sealos-io-v1-usergroupbinding
failurePolicy: Fail
name: musergroupbinding.kb.io
rules:
- apiGroups:
- user.sealos.io
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- usergroupbindings
sideEffects: None
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
creationTimestamp: null
name: validating-webhook-configuration
webhooks:
- admissionReviewVersions:
- v1
clientConfig:
service:
name: webhook-service
namespace: system
path: /validate-user-sealos-io-v1-user
failurePolicy: Fail
name: vuser.kb.io
rules:
- apiGroups:
- user.sealos.io
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- users
sideEffects: None
- admissionReviewVersions:
- v1
clientConfig:
service:
name: webhook-service
namespace: system
path: /validate-user-sealos-io-v1-usergroup
failurePolicy: Fail
name: vusergroup.kb.io
rules:
- apiGroups:
- user.sealos.io
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- usergroups
sideEffects: None
- admissionReviewVersions:
- v1
clientConfig:
service:
name: webhook-service
namespace: system
path: /validate-user-sealos-io-v1-usergroupbinding
failurePolicy: Fail
name: vusergroupbinding.kb.io
rules:
- apiGroups:
- user.sealos.io
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- usergroupbindings
sideEffects: None
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: webhook-service
namespace: system
spec:
ports:
- port: 443
protocol: TCP
targetPort: 9443
selector:
control-plane: controller-manager
+161
View File
@@ -0,0 +1,161 @@
/*
Copyright 2022 cuisongliu@qq.com.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cache
import (
"context"
"github.com/go-logr/logr"
userv1 "github.com/labring/sealos/controllers/user/api/v1"
"github.com/labring/sealos/controllers/user/controllers/helper"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
)
type Cache struct {
Logger logr.Logger
client.Client
}
func NewCache(cli client.Client, logger logr.Logger) *Cache {
return &Cache{
Logger: logger,
Client: cli,
}
}
func SetupCache(mgr ctrl.Manager) error {
ugb := &userv1.UserGroupBinding{}
ugRefFunc := func(obj client.Object) []string {
return []string{obj.(*userv1.UserGroupBinding).UserGroupRef}
}
subjectKindFunc := func(obj client.Object) []string {
return []string{obj.(*userv1.UserGroupBinding).Subject.Kind}
}
subjectNameFunc := func(obj client.Object) []string {
return []string{obj.(*userv1.UserGroupBinding).Subject.Name}
}
if err := mgr.GetFieldIndexer().IndexField(context.TODO(), ugb, "userGroupRef", ugRefFunc); err != nil {
return err
}
if err := mgr.GetFieldIndexer().IndexField(context.TODO(), ugb, "subject.kind", subjectKindFunc); err != nil {
return err
}
if err := mgr.GetFieldIndexer().IndexField(context.TODO(), ugb, "subject.name", subjectNameFunc); err != nil {
return err
}
return nil
}
func (r *Cache) FetchNamespaceFromUserGroup(ctx context.Context, userGroup string) (namespaces []userv1.UserGroupBinding) {
ugUserBindingList := make([]userv1.UserGroupBindingList, 0)
var ugUserBinding userv1.UserGroupBindingList
if err := r.List(ctx, &ugUserBinding, client.MatchingFields{"userGroupRef": userGroup}); err != nil {
r.Logger.Error(err, "list ugUserBinding error from cache", "userGroupRef", userGroup)
}
ugUserBindingList = append(ugUserBindingList, ugUserBinding)
if err := r.List(ctx, &ugUserBinding, client.MatchingFields{"subject.kind": "Namespace"}); err != nil {
r.Logger.Error(err, "list ugUserBinding error from cache", "subject.kind", "User")
}
ugUserBindingList = append(ugUserBindingList, ugUserBinding)
var newAny helper.Any
for i, item := range ugUserBindingList {
newIAny := helper.NewAny(nil)
for _, j := range item.Items {
newIAny = newIAny.InsertValue(j.Name, j)
}
if i == 0 {
newAny = newIAny
}
newAny = newAny.Intersection(newIAny)
}
values := newAny.ListValue()
for _, value := range values {
if ns, ok := value.(userv1.UserGroupBinding); ok {
namespaces = append(namespaces, ns)
}
}
return
}
func (r *Cache) FetchUserFromUserGroup(ctx context.Context, userGroup string) (users []userv1.UserGroupBinding) {
ugUserBindingList := make([]userv1.UserGroupBindingList, 0)
var ugUserBinding userv1.UserGroupBindingList
if err := r.List(ctx, &ugUserBinding, client.MatchingFields{"userGroupRef": userGroup}); err != nil {
r.Logger.Error(err, "list ugUserBinding error from cache", "userGroupRef", userGroup)
}
ugUserBindingList = append(ugUserBindingList, ugUserBinding)
if err := r.List(ctx, &ugUserBinding, client.MatchingFields{"subject.kind": "User"}); err != nil {
r.Logger.Error(err, "list ugUserBinding error from cache", "subject.kind", "User")
}
ugUserBindingList = append(ugUserBindingList, ugUserBinding)
var newAny helper.Any
for i, item := range ugUserBindingList {
newIAny := helper.NewAny(nil)
for _, j := range item.Items {
newIAny = newIAny.InsertValue(j.Name, j)
}
if i == 0 {
newAny = newIAny
}
newAny = newAny.Intersection(newIAny)
}
values := newAny.ListValue()
for _, value := range values {
if u, ok := value.(userv1.UserGroupBinding); ok {
users = append(users, u)
}
}
return
}
func (r *Cache) FetchUserGroupFromUser(ctx context.Context, user string) (userGroups []userv1.UserGroupBinding) {
ugUserBindingList := make([]userv1.UserGroupBindingList, 0)
var ugUserBinding userv1.UserGroupBindingList
if err := r.List(ctx, &ugUserBinding, client.MatchingFields{"subject.name": user}); err != nil {
r.Logger.Error(err, "list ugUserBinding error from cache", "subject.name", user)
}
ugUserBindingList = append(ugUserBindingList, ugUserBinding)
if err := r.List(ctx, &ugUserBinding, client.MatchingFields{"subject.kind": "User"}); err != nil {
r.Logger.Error(err, "list ugUserBinding error from cache", "subject.kind", "User")
}
ugUserBindingList = append(ugUserBindingList, ugUserBinding)
var newAny helper.Any
for i, item := range ugUserBindingList {
newIAny := helper.NewAny(nil)
for _, j := range item.Items {
newIAny = newIAny.InsertValue(j.Name, j)
}
if i == 0 {
newAny = newIAny
}
newAny = newAny.Intersection(newIAny)
}
values := newAny.ListValue()
for _, value := range values {
if u, ok := value.(userv1.UserGroupBinding); ok {
userGroups = append(userGroups, u)
}
}
return
}
@@ -48,7 +48,8 @@ import (
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)
const userAnnotationOwnerKey = "user.sealos.io/creator"
var userAnnotationOwnerKey = userv1.UserAnnotationOwnerKey
const clusterRoleByCreate = "sealos-user-create-role"
const clusterRoleByManager = "sealos-user-manager-role"
@@ -94,38 +94,11 @@ func (r *UserGroupBindingReconciler) SetupWithManager(mgr ctrl.Manager) error {
}
r.Scheme = mgr.GetScheme()
r.cache = mgr.GetCache()
if err := r.InstallCache(mgr); err != nil {
return err
}
r.Logger.V(1).Info("init reconcile controller user group binding")
return ctrl.NewControllerManagedBy(mgr).
For(&userv1.UserGroupBinding{}).
Complete(r)
}
func (r *UserGroupBindingReconciler) InstallCache(mgr ctrl.Manager) error {
ugb := &userv1.UserGroupBinding{}
ugRefFunc := func(obj client.Object) []string {
return []string{obj.(*userv1.UserGroupBinding).UserGroupRef}
}
subjectKindFunc := func(obj client.Object) []string {
return []string{obj.(*userv1.UserGroupBinding).Subject.Kind}
}
subjectNameFunc := func(obj client.Object) []string {
return []string{obj.(*userv1.UserGroupBinding).Subject.Name}
}
if err := mgr.GetFieldIndexer().IndexField(context.TODO(), ugb, "userGroupRef", ugRefFunc); err != nil {
return err
}
if err := mgr.GetFieldIndexer().IndexField(context.TODO(), ugb, "subject.kind", subjectKindFunc); err != nil {
return err
}
if err := mgr.GetFieldIndexer().IndexField(context.TODO(), ugb, "subject.name", subjectNameFunc); err != nil {
return err
}
return nil
}
func (r *UserGroupBindingReconciler) updateStatus(ctx context.Context, nn types.NamespacedName, status *userv1.UserGroupBindingStatus) error {
if err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
original := &userv1.UserGroupBinding{}
@@ -19,6 +19,8 @@ package controllers
import (
"context"
"github.com/labring/sealos/controllers/user/controllers/cache"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"golang.org/x/sync/errgroup"
@@ -109,39 +111,6 @@ func (r *UserGroupNamespaceBindingController) syncNamespace(ctx context.Context,
}
}
func (r *UserGroupNamespaceBindingController) mergeFromUser(ctx context.Context, ugBinding *userv1.UserGroupBinding) (users []userv1.UserGroupBinding) {
ugUserBindingList := make([]userv1.UserGroupBindingList, 0)
var ugUserBinding userv1.UserGroupBindingList
if err := r.List(ctx, &ugUserBinding, client.MatchingFields{"userGroupRef": ugBinding.UserGroupRef}); err != nil {
r.Logger.Error(err, "list ugUserBinding error from cache", "userGroupRef", ugBinding.UserGroupRef)
}
ugUserBindingList = append(ugUserBindingList, ugUserBinding)
if err := r.List(ctx, &ugUserBinding, client.MatchingFields{"subject.kind": "User"}); err != nil {
r.Logger.Error(err, "list ugUserBinding error from cache", "subject.kind", "User")
}
ugUserBindingList = append(ugUserBindingList, ugUserBinding)
var newAny helper.Any
for i, item := range ugUserBindingList {
newIAny := helper.NewAny(nil)
for _, j := range item.Items {
newIAny = newIAny.InsertValue(j.Name, j)
}
if i == 0 {
newAny = newIAny
}
newAny = newAny.Intersection(newIAny)
}
values := newAny.ListValue()
for _, value := range values {
if u, ok := value.(userv1.UserGroupBinding); ok {
users = append(users, u)
}
}
return
}
func (r *UserGroupNamespaceBindingController) syncRoleBinding(ctx context.Context, ugBinding *userv1.UserGroupBinding) {
roleBindingConditionType := userv1.ConditionType("UGNamespaceBindingSyncReady")
condition := &userv1.Condition{
@@ -152,7 +121,7 @@ func (r *UserGroupNamespaceBindingController) syncRoleBinding(ctx context.Contex
Reason: string(userv1.Ready),
Message: "sync ug namespace binding successfully",
}
users := r.mergeFromUser(ctx, ugBinding)
users := cache.NewCache(r.Client, r.Logger).FetchUserFromUserGroup(ctx, ugBinding.UserGroupRef)
defer r.saveCondition(ugBinding, condition)
userName := ugBinding.Annotations[userAnnotationOwnerKey]
@@ -19,6 +19,8 @@ package controllers
import (
"context"
"github.com/labring/sealos/controllers/user/controllers/cache"
"golang.org/x/sync/errgroup"
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -172,38 +174,6 @@ func (r *UserGroupUserBindingController) syncClusterRoleBindingByOwner(ctx conte
}
}
}
func (r *UserGroupUserBindingController) mergeFromNamespace(ctx context.Context, ugBinding *userv1.UserGroupBinding) (users []userv1.UserGroupBinding) {
ugUserBindingList := make([]userv1.UserGroupBindingList, 0)
var ugUserBinding userv1.UserGroupBindingList
if err := r.List(ctx, &ugUserBinding, client.MatchingFields{"userGroupRef": ugBinding.UserGroupRef}); err != nil {
r.Logger.Error(err, "list ugUserBinding error from cache", "userGroupRef", ugBinding.UserGroupRef)
}
ugUserBindingList = append(ugUserBindingList, ugUserBinding)
if err := r.List(ctx, &ugUserBinding, client.MatchingFields{"subject.kind": "Namespace"}); err != nil {
r.Logger.Error(err, "list ugUserBinding error from cache", "subject.kind", "User")
}
ugUserBindingList = append(ugUserBindingList, ugUserBinding)
var newAny helper.Any
for i, item := range ugUserBindingList {
newIAny := helper.NewAny(nil)
for _, j := range item.Items {
newIAny = newIAny.InsertValue(j.Name, j)
}
if i == 0 {
newAny = newIAny
}
newAny = newAny.Intersection(newIAny)
}
values := newAny.ListValue()
for _, value := range values {
if u, ok := value.(userv1.UserGroupBinding); ok {
users = append(users, u)
}
}
return
}
func (r *UserGroupUserBindingController) syncRoleBinding(ctx context.Context, ugBinding *userv1.UserGroupBinding) {
roleBindingConditionType := userv1.ConditionType("UGNamespaceBindingSyncReady")
@@ -215,7 +185,8 @@ func (r *UserGroupUserBindingController) syncRoleBinding(ctx context.Context, ug
Reason: string(userv1.Ready),
Message: "sync ug namespace binding successfully",
}
namespaces := r.mergeFromNamespace(ctx, ugBinding)
namespaces := cache.NewCache(r.Client, r.Logger).FetchNamespaceFromUserGroup(ctx, ugBinding.UserGroupRef)
defer r.saveCondition(ugBinding, condition)
userName := ugBinding.Annotations[userAnnotationOwnerKey]
+217 -48
View File
@@ -826,22 +826,6 @@ metadata:
---
apiVersion: v1
kind: Service
metadata:
labels:
control-plane: controller-manager
name: user-controller-manager-api-service
namespace: user-system
spec:
ports:
- name: http
port: 8088
protocol: TCP
targetPort: 8088
selector:
control-plane: controller-manager
---
apiVersion: v1
kind: Service
metadata:
labels:
control-plane: controller-manager
@@ -856,6 +840,19 @@ spec:
selector:
control-plane: controller-manager
---
apiVersion: v1
kind: Service
metadata:
name: user-webhook-service
namespace: user-system
spec:
ports:
- port: 443
protocol: TCP
targetPort: 9443
selector:
control-plane: controller-manager
---
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -876,6 +873,47 @@ spec:
control-plane: controller-manager
spec:
containers:
- args:
- --health-probe-bind-address=:8081
- --metrics-bind-address=127.0.0.1:8080
- --leader-elect
command:
- /manager
image: ghcr.io/labring/user-controller:dev
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
path: /healthz
port: 8081
initialDelaySeconds: 15
periodSeconds: 20
name: manager
ports:
- containerPort: 9443
name: webhook-server
protocol: TCP
readinessProbe:
httpGet:
path: /readyz
port: 8081
initialDelaySeconds: 5
periodSeconds: 10
resources:
limits:
cpu: 500m
memory: 128Mi
requests:
cpu: 10m
memory: 64Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
volumeMounts:
- mountPath: /tmp/k8s-webhook-server/serving-certs
name: cert
readOnly: true
- args:
- --secure-listen-address=0.0.0.0:8443
- --upstream=http://127.0.0.1:8080/
@@ -899,39 +937,170 @@ spec:
capabilities:
drop:
- ALL
- args:
- --health-probe-bind-address=:8081
- --metrics-bind-address=127.0.0.1:8080
- --leader-elect
command:
- /manager
image: ghcr.io/labring/user-controller:dev
livenessProbe:
httpGet:
path: /healthz
port: 8081
initialDelaySeconds: 15
periodSeconds: 20
name: manager
readinessProbe:
httpGet:
path: /readyz
port: 8081
initialDelaySeconds: 5
periodSeconds: 10
resources:
limits:
cpu: 500m
memory: 128Mi
requests:
cpu: 10m
memory: 64Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
securityContext:
runAsNonRoot: true
serviceAccountName: user-controller-manager
terminationGracePeriodSeconds: 10
volumes:
- name: cert
secret:
defaultMode: 420
secretName: webhook-server-cert
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: user-serving-cert
namespace: user-system
spec:
dnsNames:
- user-webhook-service.user-system.svc
- user-webhook-service.user-system.svc.cluster.local
issuerRef:
kind: Issuer
name: user-selfsigned-issuer
secretName: webhook-server-cert
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: user-selfsigned-issuer
namespace: user-system
spec:
selfSigned: {}
---
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
annotations:
cert-manager.io/inject-ca-from: user-system/user-serving-cert
name: user-mutating-webhook-configuration
webhooks:
- admissionReviewVersions:
- v1
clientConfig:
service:
name: user-webhook-service
namespace: user-system
path: /mutate-user-sealos-io-v1-user
failurePolicy: Fail
name: muser.kb.io
rules:
- apiGroups:
- user.sealos.io
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- users
sideEffects: None
- admissionReviewVersions:
- v1
clientConfig:
service:
name: user-webhook-service
namespace: user-system
path: /mutate-user-sealos-io-v1-usergroup
failurePolicy: Fail
name: musergroup.kb.io
rules:
- apiGroups:
- user.sealos.io
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- usergroups
sideEffects: None
- admissionReviewVersions:
- v1
clientConfig:
service:
name: user-webhook-service
namespace: user-system
path: /mutate-user-sealos-io-v1-usergroupbinding
failurePolicy: Fail
name: musergroupbinding.kb.io
rules:
- apiGroups:
- user.sealos.io
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- usergroupbindings
sideEffects: None
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
annotations:
cert-manager.io/inject-ca-from: user-system/user-serving-cert
name: user-validating-webhook-configuration
webhooks:
- admissionReviewVersions:
- v1
clientConfig:
service:
name: user-webhook-service
namespace: user-system
path: /validate-user-sealos-io-v1-user
failurePolicy: Fail
name: vuser.kb.io
rules:
- apiGroups:
- user.sealos.io
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- users
sideEffects: None
- admissionReviewVersions:
- v1
clientConfig:
service:
name: user-webhook-service
namespace: user-system
path: /validate-user-sealos-io-v1-usergroup
failurePolicy: Fail
name: vusergroup.kb.io
rules:
- apiGroups:
- user.sealos.io
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- usergroups
sideEffects: None
- admissionReviewVersions:
- v1
clientConfig:
service:
name: user-webhook-service
namespace: user-system
path: /validate-user-sealos-io-v1-usergroupbinding
failurePolicy: Fail
name: vusergroupbinding.kb.io
rules:
- apiGroups:
- user.sealos.io
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- usergroupbindings
sideEffects: None
+30 -26
View File
@@ -20,15 +20,16 @@ import (
"context"
"flag"
"os"
"sync"
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
// to ensure that exec-entrypoint and run can make use of them.
_ "k8s.io/client-go/plugin/pkg/client/auth"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"github.com/labring/sealos/controllers/user/controllers/cache"
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
// to ensure that exec-entrypoint and run can make use of them.
_ "k8s.io/client-go/plugin/pkg/client/auth"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
@@ -120,6 +121,25 @@ func main() {
setupLog.Error(err, "unable to create controller", "controller", "Payment")
os.Exit(1)
}
if err = cache.SetupCache(mgr); err != nil {
setupLog.Error(err, "unable to cache controller")
os.Exit(1)
}
if err = (&userv1.User{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "User")
os.Exit(1)
}
setupLog.Info("add ug and ugb webhooks")
if err = (&userv1.UserGroup{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "UserGroup")
os.Exit(1)
}
if err = (&userv1.UserGroupBinding{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "UserGroupBinding")
os.Exit(1)
}
//+kubebuilder:scaffold:builder
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
@@ -132,25 +152,9 @@ func main() {
}
ctx, cancel := context.WithCancel(context.TODO())
defer cancel()
go func() {
setupLog.Info("starting manager")
if err := mgr.Start(ctx); err != nil {
setupLog.Error(err, "failed to running manager")
os.Exit(1)
}
}()
done := make(chan struct{})
go func() {
if mgr.GetCache().WaitForCacheSync(context.Background()) {
done <- struct{}{}
}
}()
<-done
go func(mgr ctrl.Manager) {
//TODO add apiserver
}(mgr)
var wg sync.WaitGroup
wg.Add(1)
wg.Wait()
setupLog.Info("starting manager")
if err = mgr.Start(ctx); err != nil {
setupLog.Error(err, "failed to running manager")
os.Exit(1)
}
}