Merge pull request #3356 from wanjunlei/nm

support customize notification receiver
This commit is contained in:
KubeSphere CI Bot
2021-03-12 16:53:01 +08:00
committed by GitHub
65 changed files with 8900 additions and 2 deletions

View File

@@ -0,0 +1,358 @@
package notification
import (
"context"
"fmt"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apis/notification/v2beta1"
"kubesphere.io/kubesphere/pkg/apiserver/query"
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource"
"reflect"
)
type Operator interface {
List(user, resource, subresource string, query *query.Query) (*api.ListResult, error)
Get(user, resource, name, subresource string) (runtime.Object, error)
Create(user, resource string, obj runtime.Object) (runtime.Object, error)
Delete(user, resource, name string) error
Update(user, resource, name string, obj runtime.Object) (runtime.Object, error)
GetObject(resource string) runtime.Object
IsKnownResource(resource, subresource string) bool
}
type operator struct {
k8sClient kubernetes.Interface
ksClient kubesphere.Interface
informers informers.InformerFactory
resourceGetter *resource.ResourceGetter
}
func NewOperator(
informers informers.InformerFactory,
k8sClient kubernetes.Interface,
ksClient kubesphere.Interface) Operator {
return &operator{
informers: informers,
k8sClient: k8sClient,
ksClient: ksClient,
resourceGetter: resource.NewResourceGetter(informers, nil),
}
}
// List objects. Only global objects will be returned if the user is nil.
// If the user is not nil, only tenant objects whose tenant label matches the user will be returned.
func (o *operator) List(user, resource, subresource string, q *query.Query) (*api.ListResult, error) {
if len(q.LabelSelector) > 0 {
q.LabelSelector = q.LabelSelector + ","
}
filter := ""
// If user is nil, it will list all global object.
if user == "" {
if isConfig(o.GetObject(resource)) {
filter = "type=default"
} else {
filter = "type=global"
}
} else {
// If the user is not nil, only return the object belong to this user.
filter = "type=tenant,user=" + user
}
q.LabelSelector = q.LabelSelector + filter
res, err := o.resourceGetter.List(resource, constants.NotificationSecretNamespace, q)
if err != nil {
return nil, err
}
if subresource == "" || resource == "secrets" {
return res, nil
}
results := &api.ListResult{}
for _, item := range res.Items {
obj := clean(item, resource, subresource)
if obj != nil {
results.Items = append(results.Items, obj)
}
}
results.TotalItems = len(results.Items)
return results, nil
}
// Get the specified object, if you want to get a global object, the user must be nil.
// If you want to get a tenant object, the user must equal to the tenant specified in labels of the object.
func (o *operator) Get(user, resource, name, subresource string) (runtime.Object, error) {
obj, err := o.resourceGetter.Get(resource, constants.NotificationSecretNamespace, name)
if err != nil {
return nil, err
}
if err := authorizer(user, obj); err != nil {
return nil, err
}
if subresource == "" || resource == "secrets" {
return obj, nil
}
res := clean(obj, resource, subresource)
if res == nil {
return nil, errors.NewNotFound(v2beta1.Resource(obj.GetObjectKind().GroupVersionKind().GroupKind().Kind), name)
}
return res, nil
}
// Create an object. A global object will be created if the user is nil.
// A tenant object will be created if the user is not nil.
func (o *operator) Create(user, resource string, obj runtime.Object) (runtime.Object, error) {
if err := appendLabel(user, obj); err != nil {
return nil, err
}
switch resource {
case v2beta1.ResourcesPluralConfig:
return o.ksClient.NotificationV2beta1().Configs().Create(context.Background(), obj.(*v2beta1.Config), v1.CreateOptions{})
case v2beta1.ResourcesPluralReceiver:
return o.ksClient.NotificationV2beta1().Receivers().Create(context.Background(), obj.(*v2beta1.Receiver), v1.CreateOptions{})
case "secrets":
return o.k8sClient.CoreV1().Secrets(constants.NotificationSecretNamespace).Create(context.Background(), obj.(*corev1.Secret), v1.CreateOptions{})
default:
return nil, errors.NewInternalError(nil)
}
}
// Delete an object. A global object will be deleted if the user is nil.
// If the user is not nil, a tenant object whose tenant label matches the user will be deleted.
func (o *operator) Delete(user, resource, name string) error {
if obj, err := o.Get(user, resource, name, ""); err != nil {
return err
} else {
if err := authorizer(user, obj); err != nil {
return err
}
}
switch resource {
case v2beta1.ResourcesPluralConfig:
return o.ksClient.NotificationV2beta1().Configs().Delete(context.Background(), name, v1.DeleteOptions{})
case v2beta1.ResourcesPluralReceiver:
return o.ksClient.NotificationV2beta1().Receivers().Delete(context.Background(), name, v1.DeleteOptions{})
case "secrets":
return o.k8sClient.CoreV1().Secrets(constants.NotificationSecretNamespace).Delete(context.Background(), name, v1.DeleteOptions{})
default:
return errors.NewInternalError(nil)
}
}
// Update an object, only a global object will be updated if the user is nil.
// If the user is not nil, a tenant object whose tenant label matches the user will be updated.
func (o *operator) Update(user, resource, name string, obj runtime.Object) (runtime.Object, error) {
if err := appendLabel(user, obj); err != nil {
return nil, err
}
if old, err := o.Get(user, resource, name, ""); err != nil {
return nil, err
} else {
if err := authorizer(user, old); err != nil {
return nil, err
}
}
switch resource {
case v2beta1.ResourcesPluralConfig:
return o.ksClient.NotificationV2beta1().Configs().Update(context.Background(), obj.(*v2beta1.Config), v1.UpdateOptions{})
case v2beta1.ResourcesPluralReceiver:
return o.ksClient.NotificationV2beta1().Receivers().Update(context.Background(), obj.(*v2beta1.Receiver), v1.UpdateOptions{})
case "secrets":
return o.k8sClient.CoreV1().Secrets(constants.NotificationSecretNamespace).Update(context.Background(), obj.(*corev1.Secret), v1.UpdateOptions{})
default:
return nil, errors.NewInternalError(nil)
}
}
func (o *operator) GetObject(resource string) runtime.Object {
switch resource {
case v2beta1.ResourcesPluralConfig:
return &v2beta1.Config{}
case v2beta1.ResourcesPluralReceiver:
return &v2beta1.Receiver{}
case "secrets":
return &corev1.Secret{}
default:
return nil
}
}
func (o *operator) IsKnownResource(resource, subresource string) bool {
if obj := o.GetObject(resource); obj == nil {
return false
}
// "" means get all types of the config or receiver.
if subresource != "dingtalk" &&
subresource != "email" &&
subresource != "slack" &&
subresource != "webhook" &&
subresource != "wechat" &&
subresource != "" {
return false
}
return true
}
// Does the user has permission to access this object.
func authorizer(user string, obj runtime.Object) error {
// If the user is not nil, it must equal to the tenant specified in labels of the object.
if user != "" && !isOwner(user, obj) {
return errors.NewForbidden(v2beta1.Resource(obj.GetObjectKind().GroupVersionKind().GroupKind().Kind), "",
fmt.Errorf("user '%s' is not the owner of object", user))
}
// If the user is nil, the object must be a global object.
if user == "" && !isGlobal(obj) {
return errors.NewForbidden(v2beta1.Resource(obj.GetObjectKind().GroupVersionKind().GroupKind().Kind), "",
fmt.Errorf("object is not a global object"))
}
return nil
}
// Is the user equal to the tenant specified in the object labels.
func isOwner(user string, obj interface{}) bool {
accessor, err := meta.Accessor(obj)
if err != nil {
klog.Errorln(err)
return false
}
return accessor.GetLabels()["user"] == user
}
func isConfig(obj runtime.Object) bool {
switch obj.(type) {
case *v2beta1.Config:
return true
default:
return false
}
}
// Is the object is a global object.
func isGlobal(obj runtime.Object) bool {
accessor, err := meta.Accessor(obj)
if err != nil {
klog.Errorln(err)
return false
}
if isConfig(obj) {
return accessor.GetLabels()["type"] == "default"
} else {
return accessor.GetLabels()["type"] == "global"
}
}
func appendLabel(user string, obj runtime.Object) error {
accessor, err := meta.Accessor(obj)
if err != nil {
klog.Errorln(err)
return err
}
labels := accessor.GetLabels()
if labels == nil {
labels = make(map[string]string)
}
if user == "" {
if isConfig(obj) {
labels["type"] = "default"
} else {
labels["type"] = "global"
}
} else {
labels["type"] = "tenant"
labels["user"] = user
}
accessor.SetLabels(labels)
return nil
}
func clean(obj interface{}, resource, subresource string) runtime.Object {
if resource == v2beta1.ResourcesPluralConfig {
config := obj.(*v2beta1.Config)
newConfig := config.DeepCopy()
newConfig.Spec = v2beta1.ConfigSpec{}
switch subresource {
case "dingtalk":
newConfig.Spec.DingTalk = config.Spec.DingTalk
case "email":
newConfig.Spec.Email = config.Spec.Email
case "slack":
newConfig.Spec.Slack = config.Spec.Slack
case "webhook":
newConfig.Spec.Webhook = config.Spec.Webhook
case "wechat":
newConfig.Spec.Wechat = config.Spec.Wechat
default:
return nil
}
if reflect.ValueOf(newConfig.Spec).IsZero() {
return nil
}
return newConfig
} else {
receiver := obj.(*v2beta1.Receiver)
newReceiver := receiver.DeepCopy()
newReceiver.Spec = v2beta1.ReceiverSpec{}
switch subresource {
case "dingtalk":
newReceiver.Spec.DingTalk = receiver.Spec.DingTalk
case "email":
newReceiver.Spec.Email = receiver.Spec.Email
case "slack":
newReceiver.Spec.Slack = receiver.Spec.Slack
case "webhook":
newReceiver.Spec.Webhook = receiver.Spec.Webhook
case "wechat":
newReceiver.Spec.Wechat = receiver.Spec.Wechat
default:
return nil
}
if reflect.ValueOf(newReceiver.Spec).IsZero() {
return nil
}
return newReceiver
}
}

View File

@@ -0,0 +1,217 @@
/*
Copyright 2020 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 notification
import (
"github.com/google/go-cmp/cmp"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
fakek8s "k8s.io/client-go/kubernetes/fake"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
fakeks "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"reflect"
"testing"
)
func TestOperator_List(t *testing.T) {
o := prepare()
tests := []struct {
result *api.ListResult
expectError error
}{
{
result: &api.ListResult{
Items: []interface{}{secret1, secret2, secret3},
TotalItems: 3,
},
},
}
for i, test := range tests {
result, err := o.List("", "secrets", "", &query.Query{
SortBy: query.FieldName,
Ascending: true,
})
if err != nil {
if !reflect.DeepEqual(err, test.expectError) {
t.Errorf("got %#v, expected %#v", err, test.expectError)
}
continue
}
if diff := cmp.Diff(result, test.result); diff != "" {
t.Errorf("case %d, %s", i, diff)
}
}
}
func TestOperator_Get(t *testing.T) {
o := prepare()
tests := []struct {
result *corev1.Secret
name string
expectError error
}{
{
result: secret1,
name: secret1.Name,
expectError: nil,
},
{
name: "foo4",
expectError: errors.NewNotFound(corev1.Resource("secret"), "foo4"),
},
}
for _, test := range tests {
result, err := o.Get("", "secrets", test.name, "")
if err != nil {
if !reflect.DeepEqual(err, test.expectError) {
t.Errorf("got %#v, expected %#v", err, test.expectError)
}
continue
}
if diff := cmp.Diff(result, test.result); diff != "" {
t.Error(diff)
}
}
}
func TestOperator_Create(t *testing.T) {
o := prepare()
tests := []struct {
result *corev1.Secret
secret *corev1.Secret
expectError error
}{
{
result: &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: constants.NotificationSecretNamespace,
Labels: map[string]string{
"type": "global",
},
},
},
secret: &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Labels: map[string]string{
"type": "global",
},
},
},
expectError: nil,
},
}
for i, test := range tests {
result, err := o.Create("", "secrets", test.secret)
if err != nil {
if !reflect.DeepEqual(err, test.expectError) {
t.Errorf("case %d, got %#v, expected %#v", i, err, test.expectError)
}
continue
}
if diff := cmp.Diff(result, test.result); diff != "" {
t.Error(diff)
}
}
}
func TestOperator_Delete(t *testing.T) {
o := prepare()
tests := []struct {
name string
expectError error
}{
{
name: "foo4",
expectError: errors.NewNotFound(corev1.Resource("secret"), "foo4"),
},
}
for i, test := range tests {
err := o.Delete("", "secrets", test.name)
if err != nil {
if test.expectError != nil && test.expectError.Error() == err.Error() {
continue
} else {
if !reflect.DeepEqual(err, test.expectError) {
t.Errorf("case %d, got %#v, expected %#v", i, err, test.expectError)
}
}
}
}
}
var (
secret1 = &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "foo1",
Namespace: constants.NotificationSecretNamespace,
Labels: map[string]string{
"type": "global",
},
},
}
secret2 = &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "foo2",
Namespace: constants.NotificationSecretNamespace,
Labels: map[string]string{
"type": "global",
},
},
}
secret3 = &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "foo3",
Namespace: constants.NotificationSecretNamespace,
Labels: map[string]string{
"type": "global",
},
},
}
secrets = []*corev1.Secret{secret1, secret2, secret3}
)
func prepare() Operator {
ksClient := fakeks.NewSimpleClientset()
k8sClient := fakek8s.NewSimpleClientset()
fakeInformerFactory := informers.NewInformerFactories(k8sClient, ksClient, nil, nil, nil, nil)
for _, secret := range secrets {
_ = fakeInformerFactory.KubernetesSharedInformerFactory().Core().V1().Secrets().Informer().GetIndexer().Add(secret)
}
return NewOperator(fakeInformerFactory, k8sClient, ksClient)
}

View File

@@ -0,0 +1,115 @@
/*
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 notification
import (
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
"strings"
)
type configGetter struct {
ksInformer ksinformers.SharedInformerFactory
}
func NewNotificationConfigGetter(informer ksinformers.SharedInformerFactory) v1alpha3.Interface {
return &configGetter{ksInformer: informer}
}
func (g *configGetter) Get(_, name string) (runtime.Object, error) {
return g.ksInformer.Notification().V2beta1().Configs().Lister().Get(name)
}
func (g *configGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
objs, err := g.ksInformer.Notification().V2beta1().Configs().Lister().List(query.Selector())
if err != nil {
return nil, err
}
var result []runtime.Object
for _, obj := range objs {
result = append(result, obj)
}
return v1alpha3.DefaultList(result, query, compare, filter), nil
}
type receiverGetter struct {
ksInformer ksinformers.SharedInformerFactory
}
func NewNotificationReceiverGetter(informer ksinformers.SharedInformerFactory) v1alpha3.Interface {
return &receiverGetter{ksInformer: informer}
}
func (g *receiverGetter) Get(_, name string) (runtime.Object, error) {
return g.ksInformer.Notification().V2beta1().Receivers().Lister().Get(name)
}
func (g *receiverGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
objs, err := g.ksInformer.Notification().V2beta1().Receivers().Lister().List(query.Selector())
if err != nil {
return nil, err
}
var result []runtime.Object
for _, obj := range objs {
result = append(result, obj)
}
return v1alpha3.DefaultList(result, query, compare, filter), nil
}
func compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftObj, err := meta.Accessor(left)
if err != nil {
return false
}
rightObj, err := meta.Accessor(right)
if err != nil {
return false
}
return v1alpha3.DefaultObjectMetaCompare(meta.AsPartialObjectMetadata(leftObj).ObjectMeta,
meta.AsPartialObjectMetadata(rightObj).ObjectMeta, field)
}
func filter(object runtime.Object, filter query.Filter) bool {
accessor, err := meta.Accessor(object)
if err != nil {
return false
}
switch filter.Field {
case query.FieldNames:
for _, name := range strings.Split(string(filter.Value), ",") {
if accessor.GetName() == name {
return true
}
}
return false
case query.FieldName:
return strings.Contains(accessor.GetName(), string(filter.Value))
default:
return true
}
}

View File

@@ -0,0 +1,140 @@
/*
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 notification
import (
"github.com/google/go-cmp/cmp"
"github.com/google/uuid"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/cache"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apis/notification/v2beta1"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
"kubesphere.io/kubesphere/pkg/server/errors"
"math/rand"
"sort"
"testing"
)
const (
Prefix = "foo"
LengthMin = 3
LengthMax = 10
)
func TestListObjects(t *testing.T) {
tests := []struct {
description string
key string
}{
{
"test name filter",
v2beta1.ResourcesPluralConfig,
},
{
"test name filter",
v2beta1.ResourcesPluralReceiver,
},
}
q := &query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: true,
Filters: map[query.Field]query.Value{query.FieldName: query.Value(Prefix)},
}
for _, test := range tests {
getter, objects, err := prepare(test.key)
if err != nil {
t.Fatal(err)
}
got, err := getter.List("", q)
if err != nil {
t.Fatal(err)
}
expected := &api.ListResult{
Items: objects,
TotalItems: len(objects),
}
if diff := cmp.Diff(got, expected); diff != "" {
t.Errorf("[%s] %T differ (-got, +want): %s", test.description, expected, diff)
}
}
}
func prepare(key string) (v1alpha3.Interface, []interface{}, error) {
client := fake.NewSimpleClientset()
informer := ksinformers.NewSharedInformerFactory(client, 0)
var obj runtime.Object
var indexer cache.Indexer
var getter func(informer ksinformers.SharedInformerFactory) v1alpha3.Interface
switch key {
case v2beta1.ResourcesPluralConfig:
indexer = informer.Notification().V2beta1().Configs().Informer().GetIndexer()
getter = NewNotificationConfigGetter
obj = &v2beta1.Config{}
case v2beta1.ResourcesPluralReceiver:
indexer = informer.Notification().V2beta1().Receivers().Informer().GetIndexer()
getter = NewNotificationReceiverGetter
obj = &v2beta1.Receiver{}
default:
return nil, nil, errors.New("unowned type %s", key)
}
num := rand.Intn(LengthMax)
if num < LengthMin {
num = LengthMin
}
var suffix []string
for i := 0; i < num; i++ {
s := uuid.New().String()
suffix = append(suffix, s)
}
sort.Strings(suffix)
var objects []interface{}
for i := 0; i < num; i++ {
val := obj.DeepCopyObject()
accessor, err := meta.Accessor(val)
if err != nil {
return nil, nil, err
}
accessor.SetName(Prefix + "-" + suffix[i])
err = indexer.Add(accessor)
if err != nil {
return nil, nil, err
}
objects = append(objects, val)
}
return getter(informer), objects, nil
}

View File

@@ -26,6 +26,7 @@ import (
devopsv1alpha3 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha3"
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1"
notificationv2beta1 "kubesphere.io/kubesphere/pkg/apis/notification/v2beta1"
tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
tenantv1alpha2 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha2"
typesv1beta1 "kubesphere.io/kubesphere/pkg/apis/types/v1beta1"
@@ -61,10 +62,12 @@ import (
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/namespace"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/networkpolicy"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/node"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/notification"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/persistentvolumeclaim"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/pod"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/role"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/rolebinding"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/secret"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/service"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/serviceaccount"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/statefulset"
@@ -92,6 +95,7 @@ func NewResourceGetter(factory informers.InformerFactory, cache cache.Cache) *Re
getters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "services"}] = service.New(factory.KubernetesSharedInformerFactory())
getters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "namespaces"}] = namespace.New(factory.KubernetesSharedInformerFactory())
getters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "configmaps"}] = configmap.New(factory.KubernetesSharedInformerFactory())
getters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "secrets"}] = secret.New(factory.KubernetesSharedInformerFactory())
getters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}] = pod.New(factory.KubernetesSharedInformerFactory())
getters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "nodes"}] = node.New(factory.KubernetesSharedInformerFactory())
getters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "serviceaccounts"}] = serviceaccount.New(factory.KubernetesSharedInformerFactory())
@@ -122,6 +126,9 @@ func NewResourceGetter(factory informers.InformerFactory, cache cache.Cache) *Re
getters[schema.GroupVersionResource{Group: "cluster.kubesphere.io", Version: "v1alpha1", Resource: "clusters"}] = cluster.New(factory.KubeSphereSharedInformerFactory())
getters[schema.GroupVersionResource{Group: "apiextensions.k8s.io", Version: "v1", Resource: "customresourcedefinitions"}] = customresourcedefinition.New(factory.ApiExtensionSharedInformerFactory())
getters[notificationv2beta1.SchemeGroupVersion.WithResource(notificationv2beta1.ResourcesPluralConfig)] = notification.NewNotificationConfigGetter(factory.KubeSphereSharedInformerFactory())
getters[notificationv2beta1.SchemeGroupVersion.WithResource(notificationv2beta1.ResourcesPluralReceiver)] = notification.NewNotificationReceiverGetter(factory.KubeSphereSharedInformerFactory())
// federated resources
getters[typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedNamespace)] = federatednamespace.New(factory.KubeSphereSharedInformerFactory())
getters[typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedDeployment)] = federateddeployment.New(factory.KubeSphereSharedInformerFactory())

View File

@@ -0,0 +1,77 @@
/*
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 secret
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
"k8s.io/api/core/v1"
)
type secretSearcher struct {
informers informers.SharedInformerFactory
}
func New(informers informers.SharedInformerFactory) v1alpha3.Interface {
return &secretSearcher{informers: informers}
}
func (s *secretSearcher) Get(namespace, name string) (runtime.Object, error) {
return s.informers.Core().V1().Secrets().Lister().Secrets(namespace).Get(name)
}
func (s *secretSearcher) List(namespace string, query *query.Query) (*api.ListResult, error) {
secrets, err := s.informers.Core().V1().Secrets().Lister().Secrets(namespace).List(query.Selector())
if err != nil {
return nil, err
}
var result []runtime.Object
for _, secret := range secrets {
result = append(result, secret)
}
return v1alpha3.DefaultList(result, query, s.compare, s.filter), nil
}
func (s *secretSearcher) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftSecret, ok := left.(*v1.Secret)
if !ok {
return false
}
rightSecret, ok := right.(*v1.Secret)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaCompare(leftSecret.ObjectMeta, rightSecret.ObjectMeta, field)
}
func (s *secretSearcher) filter(object runtime.Object, filter query.Filter) bool {
secret, ok := object.(*v1.Secret)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaFilter(secret.ObjectMeta, filter)
}