refactor application controller

Signed-off-by: zackzhang <zackzhang@yunify.com>
This commit is contained in:
Zack Zhang
2020-12-29 16:18:31 +08:00
committed by hongming
parent fe6c5de00f
commit f20c1f33f1
69 changed files with 1015 additions and 3155 deletions

View File

@@ -1,87 +0,0 @@
/*
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 application
import (
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"sigs.k8s.io/application/api/v1beta1"
)
type appSearcher struct {
//informer externalversions.SharedInformerFactory
}
func NewApplicationSearcher(informers interface{}) v1alpha2.Interface {
return &appSearcher{}
}
func (s *appSearcher) Get(namespace, name string) (interface{}, error) {
//return s.informer.App().V1beta1().Applications().Lister().Applications(namespace).Get(name)
panic("")
}
func (s *appSearcher) match(match map[string]string, item *v1beta1.Application) bool {
for k, v := range match {
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *appSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Application) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *appSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
//apps, err := s.informer.App().V1beta1().Applications().Lister().Applications(namespace).List(labels.Everything())
//
//if err != nil {
// return nil, err
//}
//
//result := make([]*v1beta1.Application, 0)
//
//if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
// result = apps
//} else {
// for _, item := range apps {
// if s.match(conditions.Match, item) && s.fuzzy(conditions.Fuzzy, item) {
// result = append(result, item)
// }
// }
//}
//sort.Slice(result, func(i, j int) bool {
// if reverse {
// i, j = j, i
// }
// return v1alpha2.ObjectMetaCompare(result[i].ObjectMeta, result[j].ObjectMeta, orderBy)
//})
//
//r := make([]interface{}, 0)
//for _, i := range result {
// r = append(r, i)
//}
//return r, nil
panic("")
}

View File

@@ -29,7 +29,6 @@ import (
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
fakeapp "kubesphere.io/kubesphere/pkg/simple/client/app/clientset/versioned/fake"
"testing"
)
@@ -213,9 +212,8 @@ func prepare() (informers.InformerFactory, error) {
ksClient := fakeks.NewSimpleClientset()
k8sClient := fakek8s.NewSimpleClientset()
istioClient := fakeistio.NewSimpleClientset()
appClient := fakeapp.NewSimpleClientset()
snapshotClient := fakesnapshot.NewSimpleClientset()
fakeInformerFactory := informers.NewInformerFactories(k8sClient, ksClient, istioClient, appClient, snapshotClient, nil)
fakeInformerFactory := informers.NewInformerFactories(k8sClient, ksClient, istioClient, snapshotClient, nil)
k8sInformerFactory := fakeInformerFactory.KubernetesSharedInformerFactory()

View File

@@ -22,7 +22,6 @@ import (
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/application"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/clusterrole"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/configmap"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/cronjob"
@@ -84,7 +83,6 @@ func NewResourceGetter(factory informers.InformerFactory) *ResourceGetter {
resourceGetters[v1alpha2.S2iRuns] = s2irun.NewS2iRunSearcher(factory.KubeSphereSharedInformerFactory())
resourceGetters[v1alpha2.S2iBuilderTemplates] = s2buildertemplate.NewS2iBuidlerTemplateSearcher(factory.KubeSphereSharedInformerFactory())
resourceGetters[v1alpha2.Workspaces] = workspace.NewWorkspaceSearcher(factory.KubeSphereSharedInformerFactory())
resourceGetters[v1alpha2.Applications] = application.NewApplicationSearcher(nil)
return &ResourceGetter{resourcesGetters: resourceGetters}

View File

@@ -17,36 +17,47 @@ limitations under the License.
package application
import (
"context"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api"
appv1beta1 "kubesphere.io/kubesphere/pkg/apis/app/v1beta1"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
"kubesphere.io/kubesphere/pkg/simple/client/app/informers/externalversions"
appv1beta1 "sigs.k8s.io/application/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
"time"
)
type applicationsGetter struct {
informer externalversions.SharedInformerFactory
c cache.Cache
}
func New(sharedInformers externalversions.SharedInformerFactory) v1alpha3.Interface {
return &applicationsGetter{informer: sharedInformers}
func New(c cache.Cache) v1alpha3.Interface {
return &applicationsGetter{c}
}
func (d *applicationsGetter) Get(namespace, name string) (runtime.Object, error) {
return d.informer.App().V1beta1().Applications().Lister().Applications(namespace).Get(name)
app := appv1beta1.Application{}
err := d.c.Get(context.Background(), types.NamespacedName{Namespace: namespace, Name: name}, &app)
if err != nil {
klog.Error(err)
return nil, err
}
return &app, nil
}
func (d *applicationsGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
applications, err := d.informer.App().V1beta1().Applications().Lister().Applications(namespace).List(query.Selector())
applications := appv1beta1.ApplicationList{}
err := d.c.List(context.Background(), &applications, &client.ListOptions{Namespace: namespace})
if err != nil {
klog.Error(err)
return nil, err
}
var result []runtime.Object
for _, app := range applications {
result = append(result, app)
for _, app := range applications.Items {
result = append(result, &app)
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil

View File

@@ -17,104 +17,78 @@ limitations under the License.
package application
import (
"github.com/google/go-cmp/cmp"
"context"
core "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/kubesphere/pkg/api"
appv1beta1 "kubesphere.io/kubesphere/pkg/apis/app/v1beta1"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/klog/v2"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/simple/client/app/clientset/versioned/fake"
"kubesphere.io/kubesphere/pkg/simple/client/app/informers/externalversions"
"path/filepath"
appv1beta1 "sigs.k8s.io/application/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"
"testing"
)
func applicationsToRuntimeObjects(applications ...*appv1beta1.Application) []runtime.Object {
var objs []runtime.Object
for _, app := range applications {
objs = append(objs, app)
var c client.Client
func createNamespace(name string, ctx context.Context) {
namespace := &core.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
}
err := c.Create(ctx, namespace)
if err != nil {
klog.Error(err)
}
return objs
}
func TestListApplications(t *testing.T) {
tests := []struct {
description string
namespace string
deployments []*appv1beta1.Application
query *query.Query
expected api.ListResult
expectedErr error
}{
{
"test name filter",
"bar2",
[]*appv1beta1.Application{
{
ObjectMeta: metav1.ObjectMeta{
Name: "foo-1",
Namespace: "bar",
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "foo-2",
Namespace: "bar",
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "bar-2",
Namespace: "bar2",
},
},
},
&query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{query.FieldNamespace: query.Value("bar2")},
},
api.ListResult{
Items: []interface{}{
&appv1beta1.Application{
ObjectMeta: metav1.ObjectMeta{
Name: "bar-2",
Namespace: "bar2",
},
},
},
TotalItems: 2,
},
nil,
func TestGetListApplications(t *testing.T) {
e := &envtest.Environment{CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "..", "..", "config", "crds")}}
cfg, err := e.Start()
if err != nil {
t.Fatal(err)
}
sch := scheme.Scheme
if err := appv1beta1.AddToScheme(sch); err != nil {
t.Fatalf("unable add APIs to scheme: %v", err)
}
stopCh := make(chan struct{})
ce, _ := cache.New(cfg, cache.Options{Scheme: sch})
go ce.Start(stopCh)
ce.WaitForCacheSync(stopCh)
c, _ = client.New(cfg, client.Options{Scheme: sch})
var labelSet1 = map[string]string{"foo": "bar"}
application := &appv1beta1.Application{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
Namespace: "foo",
Labels: labelSet1,
},
}
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
objs := applicationsToRuntimeObjects(test.deployments...)
client := fake.NewSimpleClientset(objs...)
ctx := context.TODO()
createNamespace("foo", ctx)
_ = c.Create(ctx, application)
informer := externalversions.NewSharedInformerFactory(client, 0)
getter := New(ce)
for _, deployment := range test.deployments {
informer.App().V1beta1().Applications().Informer().GetIndexer().Add(deployment)
}
getter := New(informer)
got, err := getter.List(test.namespace, test.query)
if test.expectedErr != nil && err != test.expectedErr {
t.Errorf("expected error, got nothing")
} else if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(got.Items, test.expected.Items); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
}
})
_, err = getter.List("foo", &query.Query{})
if err != nil {
t.Fatal(err)
}
_, err = getter.Get("foo", "bar")
if err != nil {
t.Fatal(err)
}
}

View File

@@ -18,7 +18,6 @@ package resource
import (
"errors"
snapshotv1beta1 "github.com/kubernetes-csi/external-snapshotter/client/v3/apis/volumesnapshot/v1beta1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/runtime"
@@ -74,6 +73,7 @@ import (
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/workspacerole"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/workspacerolebinding"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/workspacetemplate"
"sigs.k8s.io/controller-runtime/pkg/cache"
)
var ErrResourceNotSupported = errors.New("resource is not supported")
@@ -82,7 +82,7 @@ type ResourceGetter struct {
getters map[schema.GroupVersionResource]v1alpha3.Interface
}
func NewResourceGetter(factory informers.InformerFactory) *ResourceGetter {
func NewResourceGetter(factory informers.InformerFactory, cache cache.Cache) *ResourceGetter {
getters := make(map[schema.GroupVersionResource]v1alpha3.Interface)
getters[schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}] = deployment.New(factory.KubernetesSharedInformerFactory())
@@ -94,9 +94,9 @@ func NewResourceGetter(factory informers.InformerFactory) *ResourceGetter {
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: "extensions", Version: "v1beta1", Resource: "ingresses"}] = ingress.New(factory.KubernetesSharedInformerFactory())
getters[schema.GroupVersionResource{Group: "app.k8s.io", Version: "v1beta1", Resource: "applications"}] = application.New(factory.ApplicationSharedInformerFactory())
getters[schema.GroupVersionResource{Group: "networking.k8s.io", Version: "v1", Resource: "networkpolicies"}] = networkpolicy.New(factory.KubernetesSharedInformerFactory())
getters[schema.GroupVersionResource{Group: "batch", Version: "v1", Resource: "jobs"}] = job.New(factory.KubernetesSharedInformerFactory())
getters[schema.GroupVersionResource{Group: "app.k8s.io", Version: "v1beta1", Resource: "applications"}] = application.New(cache)
// kubesphere resources
getters[devopsv1alpha3.SchemeGroupVersion.WithResource(devopsv1alpha3.ResourcePluralDevOpsProject)] = devops.New(factory.KubeSphereSharedInformerFactory())

View File

@@ -28,7 +28,6 @@ import (
"kubesphere.io/kubesphere/pkg/apiserver/query"
fakeks "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
"kubesphere.io/kubesphere/pkg/informers"
fakeapp "kubesphere.io/kubesphere/pkg/simple/client/app/clientset/versioned/fake"
"testing"
)
@@ -107,15 +106,14 @@ func prepare() *ResourceGetter {
ksClient := fakeks.NewSimpleClientset()
k8sClient := fakek8s.NewSimpleClientset()
istioClient := fakeistio.NewSimpleClientset()
appClient := fakeapp.NewSimpleClientset()
snapshotClient := fakesnapshot.NewSimpleClientset()
apiextensionsClient := fakeapiextensions.NewSimpleClientset()
fakeInformerFactory := informers.NewInformerFactories(k8sClient, ksClient, istioClient, appClient, snapshotClient, apiextensionsClient)
fakeInformerFactory := informers.NewInformerFactories(k8sClient, ksClient, istioClient, snapshotClient, apiextensionsClient)
for _, namespace := range namespaces {
fakeInformerFactory.KubernetesSharedInformerFactory().Core().V1().
Namespaces().Informer().GetIndexer().Add(namespace)
}
return NewResourceGetter(fakeInformerFactory)
return NewResourceGetter(fakeInformerFactory, nil)
}