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:
KubeSphere CI Bot
2024-09-06 11:05:52 +08:00
committed by GitHub
parent b5015ec7b9
commit 447a51f08b
8557 changed files with 546695 additions and 1146174 deletions

View File

@@ -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 {

View File

@@ -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

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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