feat: kubesphere 4.0 (#6115)
* feat: kubesphere 4.0 Signed-off-by: ci-bot <ci-bot@kubesphere.io> * feat: kubesphere 4.0 Signed-off-by: ci-bot <ci-bot@kubesphere.io> --------- Signed-off-by: ci-bot <ci-bot@kubesphere.io> Co-authored-by: ks-ci-bot <ks-ci-bot@example.com> Co-authored-by: joyceliu <joyceliu@yunify.com>
This commit is contained in:
committed by
GitHub
parent
b5015ec7b9
commit
447a51f08b
@@ -1,20 +1,7 @@
|
||||
/*
|
||||
|
||||
Copyright 2021 The KubeSphere Authors.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
* Please refer to the LICENSE file in the root directory of the project.
|
||||
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package quota
|
||||
|
||||
@@ -172,10 +159,9 @@ func (a *accessor) GetQuotas(namespaceName string) ([]corev1.ResourceQuota, erro
|
||||
}
|
||||
|
||||
func (a *accessor) waitForReadyResourceQuotaNames(namespaceName string) ([]string, error) {
|
||||
ctx := context.TODO()
|
||||
var resourceQuotaNames []string
|
||||
// wait for a valid mapping cache. The overall response can be delayed for up to 10 seconds.
|
||||
err := utilwait.PollImmediate(100*time.Millisecond, 8*time.Second, func() (done bool, err error) {
|
||||
err := utilwait.PollUntilContextTimeout(context.TODO(), 100*time.Millisecond, 8*time.Second, true, func(ctx context.Context) (done bool, err error) {
|
||||
resourceQuotaNames, err = resourceQuotaNamesFor(ctx, a.client, namespaceName)
|
||||
// if we can't find the namespace yet, just wait for the cache to update. Requests to non-existent namespaces
|
||||
// may hang, but those people are doing something wrong and namespace lifecycle should reject them.
|
||||
@@ -191,10 +177,9 @@ func (a *accessor) waitForReadyResourceQuotaNames(namespaceName string) ([]strin
|
||||
}
|
||||
|
||||
func (a *accessor) waitForReadyNamespacedResourceQuotas(namespaceName string) ([]corev1.ResourceQuota, error) {
|
||||
ctx := context.TODO()
|
||||
var resourceQuotas []corev1.ResourceQuota
|
||||
// wait for a valid mapping cache. The overall response can be delayed for up to 10 seconds.
|
||||
err := utilwait.PollImmediate(100*time.Millisecond, 8*time.Second, func() (done bool, err error) {
|
||||
err := utilwait.PollUntilContextTimeout(context.TODO(), 100*time.Millisecond, 8*time.Second, true, func(ctx context.Context) (done bool, err error) {
|
||||
resourceQuotaList := &corev1.ResourceQuotaList{}
|
||||
err = a.client.List(ctx, resourceQuotaList, &client.ListOptions{Namespace: namespaceName})
|
||||
if err != nil {
|
||||
|
||||
@@ -1,20 +1,7 @@
|
||||
/*
|
||||
|
||||
Copyright 2021 The KubeSphere Authors.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
* Please refer to the LICENSE file in the root directory of the project.
|
||||
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package quota
|
||||
|
||||
|
||||
@@ -1,29 +1,16 @@
|
||||
/*
|
||||
|
||||
Copyright 2021 The KubeSphere Authors.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
* Please refer to the LICENSE file in the root directory of the project.
|
||||
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package quota
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/equality"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
@@ -32,6 +19,11 @@ import (
|
||||
"k8s.io/client-go/tools/record"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/utils/clock"
|
||||
quotav1alpha2 "kubesphere.io/api/quota/v1alpha2"
|
||||
tenantv1alpha1 "kubesphere.io/api/tenant/v1beta1"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
"sigs.k8s.io/controller-runtime/pkg/handler"
|
||||
@@ -39,32 +31,24 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
"sigs.k8s.io/controller-runtime/pkg/source"
|
||||
|
||||
quotav1alpha2 "kubesphere.io/api/quota/v1alpha2"
|
||||
tenantv1alpha1 "kubesphere.io/api/tenant/v1alpha1"
|
||||
|
||||
quotav1 "kubesphere.io/kubesphere/kube/pkg/quota/v1"
|
||||
evaluatorcore "kubesphere.io/kubesphere/kube/pkg/quota/v1/evaluator/core"
|
||||
"kubesphere.io/kubesphere/kube/pkg/quota/v1/generic"
|
||||
"kubesphere.io/kubesphere/kube/pkg/quota/v1/install"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
kscontroller "kubesphere.io/kubesphere/pkg/controller"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
|
||||
k8sinformers "k8s.io/client-go/informers"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
quotav1 "kubesphere.io/kubesphere/kube/pkg/quota/v1"
|
||||
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller"
|
||||
)
|
||||
|
||||
const (
|
||||
ControllerName = "resourcequota-controller"
|
||||
controllerName = "resourcequota"
|
||||
DefaultResyncPeriod = 5 * time.Minute
|
||||
DefaultMaxConcurrentReconciles = 8
|
||||
)
|
||||
|
||||
var _ kscontroller.Controller = &Reconciler{}
|
||||
var _ reconcile.Reconciler = &Reconciler{}
|
||||
|
||||
// Reconciler reconciles a Workspace object
|
||||
type Reconciler struct {
|
||||
client.Client
|
||||
@@ -75,27 +59,25 @@ type Reconciler struct {
|
||||
|
||||
MaxConcurrentReconciles int
|
||||
// Controls full recalculation of quota usage
|
||||
ResyncPeriod time.Duration
|
||||
InformerFactory k8sinformers.SharedInformerFactory
|
||||
ResyncPeriod time.Duration
|
||||
|
||||
scheme *runtime.Scheme
|
||||
}
|
||||
|
||||
func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
r.logger = ctrl.Log.WithName("controllers").WithName(ControllerName)
|
||||
r.recorder = mgr.GetEventRecorderFor(ControllerName)
|
||||
func (r *Reconciler) Name() string {
|
||||
return controllerName
|
||||
}
|
||||
|
||||
func (r *Reconciler) SetupWithManager(mgr *kscontroller.Manager) error {
|
||||
r.logger = ctrl.Log.WithName("controllers").WithName(controllerName)
|
||||
r.recorder = mgr.GetEventRecorderFor(controllerName)
|
||||
r.scheme = mgr.GetScheme()
|
||||
r.registry = generic.NewRegistry(install.NewQuotaConfigurationForControllers(
|
||||
generic.ListerFuncForResourceFunc(r.InformerFactory.ForResource)).Evaluators())
|
||||
if r.Client == nil {
|
||||
r.Client = mgr.GetClient()
|
||||
}
|
||||
if r.MaxConcurrentReconciles <= 0 {
|
||||
r.MaxConcurrentReconciles = DefaultMaxConcurrentReconciles
|
||||
}
|
||||
r.ResyncPeriod = time.Duration(math.Max(float64(r.ResyncPeriod), float64(DefaultResyncPeriod)))
|
||||
r.registry = generic.NewRegistry(install.NewQuotaConfigurationForControllers(mgr.GetClient()).Evaluators())
|
||||
r.Client = mgr.GetClient()
|
||||
r.MaxConcurrentReconciles = DefaultMaxConcurrentReconciles
|
||||
r.ResyncPeriod = DefaultResyncPeriod
|
||||
c, err := ctrl.NewControllerManagedBy(mgr).
|
||||
Named(ControllerName).
|
||||
Named(controllerName).
|
||||
WithOptions(controller.Options{
|
||||
MaxConcurrentReconciles: r.MaxConcurrentReconciles,
|
||||
}).
|
||||
@@ -121,8 +103,8 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
}
|
||||
realClock := clock.RealClock{}
|
||||
for _, resource := range resources {
|
||||
err := c.Watch(
|
||||
&source.Kind{Type: resource},
|
||||
if err = c.Watch(
|
||||
source.Kind(mgr.GetCache(), resource),
|
||||
handler.EnqueueRequestsFromMapFunc(r.mapper),
|
||||
predicate.Funcs{
|
||||
GenericFunc: func(e event.GenericEvent) bool {
|
||||
@@ -151,19 +133,17 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
DeleteFunc: func(e event.DeleteEvent) bool {
|
||||
return true
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Reconciler) mapper(h client.Object) []reconcile.Request {
|
||||
func (r *Reconciler) mapper(ctx context.Context, h client.Object) []reconcile.Request {
|
||||
// check if the quota controller can evaluate this kind, if not, ignore it altogether...
|
||||
var result []reconcile.Request
|
||||
evaluators := r.registry.List()
|
||||
ctx := context.TODO()
|
||||
resourceQuotaNames, err := resourceQuotaNamesFor(ctx, r.Client, h.GetNamespace())
|
||||
if err != nil {
|
||||
klog.Errorf("failed to get resource quota names for: %v %T %v, err: %v", h.GetNamespace(), h, h.GetName(), err)
|
||||
@@ -207,7 +187,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
r.recorder.Event(resourceQuota, corev1.EventTypeNormal, "Synced", "Synced successfully")
|
||||
r.recorder.Event(resourceQuota, corev1.EventTypeNormal, kscontroller.Synced, kscontroller.MessageResourceSynced)
|
||||
return ctrl.Result{RequeueAfter: r.ResyncPeriod}, nil
|
||||
}
|
||||
|
||||
@@ -247,6 +227,10 @@ func (r *Reconciler) syncQuotaForNamespaces(originalQuota *quotav1alpha2.Resourc
|
||||
return err
|
||||
}
|
||||
|
||||
if quota.Status.Namespaces == nil {
|
||||
quota.Status.Namespaces = make([]quotav1alpha2.ResourceQuotaStatusByNamespace, 0)
|
||||
}
|
||||
|
||||
matchingNamespaceNames := make([]string, 0)
|
||||
for _, namespace := range matchingNamespaceList.Items {
|
||||
matchingNamespaceNames = append(matchingNamespaceNames, namespace.Name)
|
||||
|
||||
@@ -1,20 +1,7 @@
|
||||
/*
|
||||
|
||||
Copyright 2021 The KubeSphere Authors.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
* Please refer to the LICENSE file in the root directory of the project.
|
||||
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package quota
|
||||
|
||||
@@ -24,6 +11,8 @@ import (
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
kscontroller "kubesphere.io/kubesphere/pkg/controller"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@@ -31,7 +20,6 @@ import (
|
||||
utilwait "k8s.io/apimachinery/pkg/util/wait"
|
||||
admissionapi "k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/klog/v2"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||
@@ -42,6 +30,7 @@ import (
|
||||
"kubesphere.io/kubesphere/kube/pkg/quota/v1/install"
|
||||
"kubesphere.io/kubesphere/kube/plugin/pkg/admission/resourcequota"
|
||||
resourcequotaapi "kubesphere.io/kubesphere/kube/plugin/pkg/admission/resourcequota/apis/resourcequota"
|
||||
"kubesphere.io/kubesphere/pkg/scheme"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -62,17 +51,26 @@ type ResourceQuotaAdmission struct {
|
||||
evaluator resourcequota.Evaluator
|
||||
}
|
||||
|
||||
func NewResourceQuotaAdmission(client client.Client, scheme *runtime.Scheme) (webhook.AdmissionHandler, error) {
|
||||
decoder, err := admission.NewDecoder(scheme)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ResourceQuotaAdmission{
|
||||
client: client,
|
||||
const webhookName = "resource-quota-webhook"
|
||||
|
||||
func (w *Webhook) Name() string {
|
||||
return webhookName
|
||||
}
|
||||
|
||||
var _ kscontroller.Controller = &Webhook{}
|
||||
|
||||
type Webhook struct {
|
||||
}
|
||||
|
||||
func (w *Webhook) SetupWithManager(mgr *kscontroller.Manager) error {
|
||||
resourceQuotaAdmission := &ResourceQuotaAdmission{
|
||||
client: mgr.GetClient(),
|
||||
lockFactory: NewDefaultLockFactory(),
|
||||
decoder: decoder,
|
||||
decoder: admission.NewDecoder(mgr.GetScheme()),
|
||||
registry: generic.NewRegistry(install.NewQuotaConfigurationForAdmission().Evaluators()),
|
||||
}, nil
|
||||
}
|
||||
mgr.GetWebhookServer().Register("/validate-quota-kubesphere-io-v1alpha2", &webhook.Admission{Handler: resourceQuotaAdmission})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ResourceQuotaAdmission) Handle(ctx context.Context, req webhook.AdmissionRequest) webhook.AdmissionResponse {
|
||||
|
||||
@@ -1,20 +1,7 @@
|
||||
/*
|
||||
|
||||
Copyright 2021 The KubeSphere Authors.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
* Please refer to the LICENSE file in the root directory of the project.
|
||||
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package quota
|
||||
|
||||
|
||||
Reference in New Issue
Block a user