Files
kubesphere/pkg/simple/controller/namespace/namespaces.go
Jeff 867129cdce add controllers
change kiali mux to go-restful

add knative

add health api
2019-03-26 01:10:35 +08:00

197 lines
5.7 KiB
Go

/*
Copyright 2019 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.
*/
package namespace
import (
"fmt"
"github.com/golang/glog"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
"time"
corev1 "k8s.io/api/core/v1"
rbac "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/errors"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
coreinformers "k8s.io/client-go/informers/core/v1"
"k8s.io/client-go/informers/rbac/v1"
rbacinformers "k8s.io/client-go/informers/rbac/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
)
var log = logf.Log.WithName("namespace-controller")
const threadiness = 2
var (
defaultRoles = []rbac.Role{
{ObjectMeta: metaV1.ObjectMeta{Name: "admin", Annotations: map[string]string{"creator": "system"}}, Rules: []rbac.PolicyRule{{Verbs: []string{"*"}, APIGroups: []string{"*"}, Resources: []string{"*"}}}},
{ObjectMeta: metaV1.ObjectMeta{Name: "operator", Annotations: map[string]string{"creator": "system"}}, Rules: []rbac.PolicyRule{{Verbs: []string{"get", "list", "watch"}, APIGroups: []string{"*"}, Resources: []string{"*"}}, {Verbs: []string{"*"}, APIGroups: []string{"", "apps", "extensions", "batch", "kubesphere.io", "account.kubesphere.io", "autoscaling"}, Resources: []string{"*"}}}},
{ObjectMeta: metaV1.ObjectMeta{Name: "viewer", Annotations: map[string]string{"creator": "system"}}, Rules: []rbac.PolicyRule{{Verbs: []string{"get", "list", "watch"}, APIGroups: []string{"*"}, Resources: []string{"*"}}}},
}
)
type NamespaceController struct {
clientset kubernetes.Interface
namespaceInformer coreinformers.NamespaceInformer
roleInformer v1.RoleInformer
workqueue workqueue.RateLimitingInterface
}
func NewNamespaceController(
clientset kubernetes.Interface,
namespaceInformer coreinformers.NamespaceInformer,
roleInformer rbacinformers.RoleInformer) *NamespaceController {
controller := &NamespaceController{
clientset: clientset,
namespaceInformer: namespaceInformer,
roleInformer: roleInformer,
workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "namespaces"),
}
log.V(3).Info("setting up event handlers")
namespaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: controller.handleObject,
UpdateFunc: func(old, new interface{}) {
newNamespace := new.(*corev1.Namespace)
oldNamespace := old.(*corev1.Namespace)
if newNamespace.ResourceVersion == oldNamespace.ResourceVersion {
return
}
controller.handleObject(new)
},
DeleteFunc: controller.handleObject,
})
roleInformer.Lister()
return controller
}
func (c *NamespaceController) Start(stopCh <-chan struct{}) error {
defer utilruntime.HandleCrash()
defer c.workqueue.ShutDown()
log.V(3).Info("starting namespace controller")
defer glog.Info("shutting down namespace controller")
// Wait for the caches to be synced before starting workers
log.Info("waiting for informer caches to sync")
if ok := cache.WaitForCacheSync(stopCh, c.namespaceInformer.Informer().HasSynced, c.roleInformer.Informer().HasSynced); !ok {
glog.Fatalf("controller exit with error: failed to wait for caches to sync")
}
log.V(3).Info("starting workers")
for i := 0; i < threadiness; i++ {
go wait.Until(c.runWorker, time.Second, stopCh)
}
<-stopCh
return nil
}
func (c *NamespaceController) runWorker() {
for c.processNextWorkItem() {
}
}
func (c *NamespaceController) processNextWorkItem() bool {
obj, shutdown := c.workqueue.Get()
if shutdown {
return false
}
err := func(obj interface{}) error {
defer c.workqueue.Done(obj)
var namespace string
var ok bool
if namespace, ok = obj.(string); !ok {
c.workqueue.Forget(obj)
utilruntime.HandleError(fmt.Errorf("expected string in workqueue but got %#v", obj))
return nil
}
if err := c.reconcile(namespace); err != nil {
c.workqueue.AddRateLimited(namespace)
return fmt.Errorf("error syncing '%s': %s, requeuing", namespace, err.Error())
}
c.workqueue.Forget(obj)
log.V(4).Info("successfully namespace synced ", "namespace", namespace)
return nil
}(obj)
if err != nil {
utilruntime.HandleError(err)
return true
}
return true
}
func (c *NamespaceController) reconcile(name string) error {
_, err := c.namespaceInformer.Lister().Get(name)
// Handler delete event
if errors.IsNotFound(err) {
return nil
}
// Handler update or create event
if err := c.checkAndCreateRoles(name); err != nil {
return err
}
return nil
}
func (c *NamespaceController) handleObject(obj interface{}) {
if namespace, ok := obj.(*corev1.Namespace); ok {
c.workqueue.AddRateLimited(namespace.Name)
}
}
// Create default roles
func (c *NamespaceController) checkAndCreateRoles(namespace string) error {
for _, role := range defaultRoles {
_, err := c.roleInformer.Lister().Roles(namespace).Get(role.Name)
if err != nil {
if errors.IsNotFound(err) {
r := role.DeepCopy()
r.Namespace = namespace
_, err = c.clientset.RbacV1().Roles(namespace).Create(r)
if err != nil && !errors.IsAlreadyExists(err) {
return err
}
} else {
return err
}
}
}
return nil
}