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,117 +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 clusterrole
import (
"sort"
rbac "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
)
type clusterRoleSearcher struct {
informer informers.SharedInformerFactory
}
func NewClusterRoleSearcher(informer informers.SharedInformerFactory) v1alpha2.Interface {
return &clusterRoleSearcher{informer: informer}
}
func (s *clusterRoleSearcher) Get(namespace, name string) (interface{}, error) {
return s.informer.Rbac().V1().ClusterRoles().Lister().Get(name)
}
func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRole) bool {
for k, v := range match {
switch k {
case v1alpha2.OwnerKind:
fallthrough
case v1alpha2.OwnerName:
kind := match[v1alpha2.OwnerKind]
name := match[v1alpha2.OwnerName]
if !k8sutil.IsControlledBy(item.OwnerReferences, kind, name) {
return false
}
case v1alpha2.UserFacing:
if v == "true" {
if !isUserFacingClusterRole(item) {
return false
}
}
default:
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
}
return true
}
func (s *clusterRoleSearcher) fuzzy(fuzzy map[string]string, item *rbac.ClusterRole) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *clusterRoleSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
clusterRoles, err := s.informer.Rbac().V1().ClusterRoles().Lister().List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*rbac.ClusterRole, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = clusterRoles
} else {
for _, item := range clusterRoles {
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
}
// cluster role created by user from kubesphere dashboard
func isUserFacingClusterRole(role *rbac.ClusterRole) bool {
if role.Annotations[constants.CreatorAnnotationKey] != "" && role.Labels[constants.WorkspaceLabelKey] == "" {
return true
}
return false
}

View File

@@ -1,90 +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 configmap
import (
"sort"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
)
type configMapSearcher struct {
informer informers.SharedInformerFactory
}
func NewConfigmapSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &configMapSearcher{informer: informers}
}
func (s *configMapSearcher) Get(namespace, name string) (interface{}, error) {
return s.informer.Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).Get(name)
}
func (s *configMapSearcher) match(match map[string]string, item *v1.ConfigMap) bool {
for k, v := range match {
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *configMapSearcher) fuzzy(fuzzy map[string]string, item *v1.ConfigMap) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *configMapSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
configMaps, err := s.informer.Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1.ConfigMap, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = configMaps
} else {
for _, item := range configMaps {
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
}

View File

@@ -1,122 +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 cronjob
import (
"sort"
v1 "k8s.io/api/batch/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
)
type cronJobSearcher struct {
informer informers.SharedInformerFactory
}
func NewCronJobSearcher(informer informers.SharedInformerFactory) v1alpha2.Interface {
return &cronJobSearcher{informer: informer}
}
func (c *cronJobSearcher) Get(namespace, name string) (interface{}, error) {
return c.informer.Batch().V1().CronJobs().Lister().CronJobs(namespace).Get(name)
}
func cronJobStatus(item *v1.CronJob) string {
if item.Spec.Suspend != nil && *item.Spec.Suspend {
return v1alpha2.StatusPaused
}
return v1alpha2.StatusRunning
}
func (*cronJobSearcher) match(match map[string]string, item *v1.CronJob) bool {
for k, v := range match {
switch k {
case v1alpha2.Status:
if cronJobStatus(item) != v {
return false
}
default:
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
}
return true
}
func (*cronJobSearcher) fuzzy(fuzzy map[string]string, item *v1.CronJob) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (*cronJobSearcher) compare(left, right *v1.CronJob, orderBy string) bool {
switch orderBy {
case v1alpha2.LastScheduleTime:
if left.Status.LastScheduleTime == nil {
return true
}
if right.Status.LastScheduleTime == nil {
return false
}
return left.Status.LastScheduleTime.Before(right.Status.LastScheduleTime)
default:
return v1alpha2.ObjectMetaCompare(left.ObjectMeta, right.ObjectMeta, orderBy)
}
}
func (c *cronJobSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
cronJobs, err := c.informer.Batch().V1().CronJobs().Lister().CronJobs(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1.CronJob, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = cronJobs
} else {
for _, item := range cronJobs {
if c.match(conditions.Match, item) && c.fuzzy(conditions.Fuzzy, item) {
result = append(result, item)
}
}
}
sort.Slice(result, func(i, j int) bool {
if reverse {
return !c.compare(result[i], result[j], orderBy)
} else {
return c.compare(result[i], result[j], orderBy)
}
})
r := make([]interface{}, 0)
for i := range result {
r = append(r, result[i])
}
return r, nil
}

View File

@@ -1,107 +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 daemonset
import (
"sort"
v1 "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
)
type daemonSetSearcher struct {
informer informers.SharedInformerFactory
}
func NewDaemonSetSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &daemonSetSearcher{informer: informers}
}
func (c *daemonSetSearcher) Get(namespace, name string) (interface{}, error) {
return c.informer.Apps().V1().DaemonSets().Lister().DaemonSets(namespace).Get(name)
}
func daemonSetStatus(item *v1.DaemonSet) string {
if item.Status.DesiredNumberScheduled == 0 && item.Status.NumberReady == 0 {
return v1alpha2.StatusStopped
} else if item.Status.DesiredNumberScheduled == item.Status.NumberReady {
return v1alpha2.StatusRunning
} else {
return v1alpha2.StatusUpdating
}
}
func (*daemonSetSearcher) match(match map[string]string, item *v1.DaemonSet) bool {
for k, v := range match {
switch k {
case v1alpha2.Status:
if daemonSetStatus(item) != v {
return false
}
default:
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
}
return true
}
func (*daemonSetSearcher) fuzzy(kv map[string]string, item *v1.DaemonSet) bool {
for k, v := range kv {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (c *daemonSetSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
daemonSets, err := c.informer.Apps().V1().DaemonSets().Lister().DaemonSets(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1.DaemonSet, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = daemonSets
} else {
for _, item := range daemonSets {
if c.match(conditions.Match, item) && c.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
}

View File

@@ -1,154 +0,0 @@
/*
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.
*/
/*
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 deployment
import (
"sort"
"strings"
"time"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"k8s.io/apimachinery/pkg/labels"
v1 "k8s.io/api/apps/v1"
)
type deploymentSearcher struct {
informer informers.SharedInformerFactory
}
func NewDeploymentSetSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &deploymentSearcher{informer: informers}
}
func (s *deploymentSearcher) Get(namespace, name string) (interface{}, error) {
return s.informer.Apps().V1().Deployments().Lister().Deployments(namespace).Get(name)
}
func deploymentStatus(item *v1.Deployment) string {
if item.Spec.Replicas != nil {
if item.Status.ReadyReplicas == 0 && *item.Spec.Replicas == 0 {
return v1alpha2.StatusStopped
} else if item.Status.ReadyReplicas == *item.Spec.Replicas {
return v1alpha2.StatusRunning
} else {
return v1alpha2.StatusUpdating
}
}
return v1alpha2.StatusStopped
}
func (*deploymentSearcher) match(kv map[string]string, item *v1.Deployment) bool {
for k, v := range kv {
switch k {
case v1alpha2.Status:
if deploymentStatus(item) != v {
return false
}
default:
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
}
return true
}
func (*deploymentSearcher) fuzzy(kv map[string]string, item *v1.Deployment) bool {
for k, v := range kv {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *deploymentSearcher) compare(a, b *v1.Deployment, orderBy string) bool {
switch orderBy {
case v1alpha2.UpdateTime:
aLastUpdateTime := s.lastUpdateTime(a)
bLastUpdateTime := s.lastUpdateTime(b)
if aLastUpdateTime.Equal(bLastUpdateTime) {
return strings.Compare(a.Name, b.Name) <= 0
}
return aLastUpdateTime.Before(bLastUpdateTime)
default:
return v1alpha2.ObjectMetaCompare(a.ObjectMeta, b.ObjectMeta, orderBy)
}
}
func (s *deploymentSearcher) lastUpdateTime(deployment *v1.Deployment) time.Time {
lastUpdateTime := deployment.CreationTimestamp.Time
for _, condition := range deployment.Status.Conditions {
if condition.LastUpdateTime.After(lastUpdateTime) {
lastUpdateTime = condition.LastUpdateTime.Time
}
}
return lastUpdateTime
}
func (s *deploymentSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
deployments, err := s.informer.Apps().V1().Deployments().Lister().Deployments(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1.Deployment, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = deployments
} else {
for _, item := range deployments {
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 s.compare(result[i], result[j], orderBy)
})
r := make([]interface{}, 0)
for _, i := range result {
r = append(r, i)
}
return r, nil
}

View File

@@ -1,106 +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 hpa
import (
"sort"
autoscalingv2 "k8s.io/api/autoscaling/v2"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
)
type hpaSearcher struct {
informers informers.SharedInformerFactory
}
func NewHpaSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &hpaSearcher{informers: informers}
}
func (s *hpaSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Autoscaling().V2().HorizontalPodAutoscalers().Lister().HorizontalPodAutoscalers(namespace).Get(name)
}
func hpaTargetMatch(item *autoscalingv2.HorizontalPodAutoscaler, kind, name string) bool {
return item.Spec.ScaleTargetRef.Kind == kind && item.Spec.ScaleTargetRef.Name == name
}
// exactly Match
func (*hpaSearcher) match(match map[string]string, item *autoscalingv2.HorizontalPodAutoscaler) bool {
for k, v := range match {
switch k {
case v1alpha2.TargetKind:
fallthrough
case v1alpha2.TargetName:
kind := match[v1alpha2.TargetKind]
name := match[v1alpha2.TargetName]
if !hpaTargetMatch(item, kind, name) {
return false
}
default:
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
}
return true
}
func (*hpaSearcher) fuzzy(fuzzy map[string]string, item *autoscalingv2.HorizontalPodAutoscaler) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *hpaSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
horizontalPodAutoscalers, err := s.informers.Autoscaling().V2().HorizontalPodAutoscalers().Lister().HorizontalPodAutoscalers(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*autoscalingv2.HorizontalPodAutoscaler, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = horizontalPodAutoscalers
} else {
for _, item := range horizontalPodAutoscalers {
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
}

View File

@@ -1,91 +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 ingress
import (
"sort"
v1 "k8s.io/api/networking/v1"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"k8s.io/apimachinery/pkg/labels"
)
type ingressSearcher struct {
informers informers.SharedInformerFactory
}
func NewIngressSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &ingressSearcher{informers: informers}
}
func (s *ingressSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Networking().V1().Ingresses().Lister().Ingresses(namespace).Get(name)
}
func (*ingressSearcher) match(match map[string]string, item *v1.Ingress) bool {
for k, v := range match {
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (*ingressSearcher) fuzzy(fuzzy map[string]string, item *v1.Ingress) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *ingressSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
ingresses, err := s.informers.Networking().V1().Ingresses().Lister().Ingresses(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1.Ingress, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = ingresses
} else {
for _, item := range ingresses {
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
}

View File

@@ -1,173 +0,0 @@
/*
Copyright 2020 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 v1alpha2
import (
"strings"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
)
const (
App = "app"
Chart = "chart"
Release = "release"
Name = "name"
Label = "label"
OwnerKind = "ownerKind"
OwnerName = "ownerName"
TargetKind = "targetKind"
TargetName = "targetName"
Role = "role"
CreateTime = "createTime"
UpdateTime = "updateTime"
StartTime = "startTime"
LastScheduleTime = "lastScheduleTime"
Annotation = "Annotation"
Keyword = "keyword"
UserFacing = "userfacing"
Status = "status"
Owner = "owner"
StatusRunning = "running"
StatusPaused = "paused"
StatusPending = "pending"
StatusUpdating = "updating"
StatusStopped = "stopped"
StatusFailed = "failed"
StatusBound = "bound"
StatusLost = "lost"
StatusComplete = "completed"
StatusWarning = "warning"
StatusUnschedulable = "unschedulable"
Deployments = "deployments"
DaemonSets = "daemonsets"
Roles = "roles"
Workspaces = "workspaces"
WorkspaceRoles = "workspaceroles"
CronJobs = "cronjobs"
ConfigMaps = "configmaps"
Ingresses = "ingresses"
Jobs = "jobs"
PersistentVolumeClaims = "persistentvolumeclaims"
Pods = "pods"
Secrets = "secrets"
Services = "services"
StatefulSets = "statefulsets"
HorizontalPodAutoscalers = "horizontalpodautoscalers"
Applications = "applications"
Nodes = "nodes"
Namespaces = "namespaces"
StorageClasses = "storageclasses"
ClusterRoles = "clusterroles"
S2iBuilderTemplates = "s2ibuildertemplates"
S2iBuilders = "s2ibuilders"
S2iRuns = "s2iruns"
)
type Interface interface {
Get(namespace, name string) (interface{}, error)
Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error)
}
func ObjectMetaExactlyMath(key, value string, item metav1.ObjectMeta) bool {
switch key {
case Name:
names := strings.Split(value, ",")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, value) && !FuzzyMatch(item.Labels, "", value) && !FuzzyMatch(item.Annotations, "", value) {
return false
}
case Owner:
for _, ownerReference := range item.OwnerReferences {
if strings.Compare(string(ownerReference.UID), value) == 0 {
return true
}
}
return false
default:
// label not exist or value not equal
if val, ok := item.Labels[key]; !ok || val != value {
return false
}
}
return true
}
func ObjectMetaFuzzyMath(key, value string, item metav1.ObjectMeta) bool {
switch key {
case Name:
if !strings.Contains(item.Name, value) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], value) {
return false
}
case Label:
if !FuzzyMatch(item.Labels, "", value) {
return false
}
case Annotation:
if !FuzzyMatch(item.Annotations, "", value) {
return false
}
return false
case App:
if !strings.Contains(item.Labels[Chart], value) && !strings.Contains(item.Labels[Release], value) {
return false
}
default:
if !FuzzyMatch(item.Labels, key, value) {
return false
}
}
return true
}
func FuzzyMatch(m map[string]string, key, value string) bool {
val, exist := m[key]
if value == "" && (!exist || val == "") {
return true
} else if value != "" && strings.Contains(val, value) {
return true
}
return false
}
func ObjectMetaCompare(left, right metav1.ObjectMeta, compareField string) bool {
switch compareField {
case CreateTime:
if left.CreationTimestamp.Time.Equal(right.CreationTimestamp.Time) {
if left.Namespace == right.Namespace {
return strings.Compare(left.Name, right.Name) < 0
}
return strings.Compare(left.Namespace, right.Namespace) < 0
}
return left.CreationTimestamp.Time.Before(right.CreationTimestamp.Time)
case Name:
fallthrough
default:
return strings.Compare(left.Name, right.Name) <= 0
}
}

View File

@@ -1,150 +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 job
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"sort"
"time"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
batchv1 "k8s.io/api/batch/v1"
"k8s.io/apimachinery/pkg/labels"
)
const (
includeCronJob = "includeCronJob"
cronJobKind = "CronJob"
s2iRunKind = "S2iRun"
includeS2iRun = "includeS2iRun"
)
type jobSearcher struct {
informers informers.SharedInformerFactory
}
func NewJobSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &jobSearcher{informers: informers}
}
func (s *jobSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Batch().V1().Jobs().Lister().Jobs(namespace).Get(name)
}
func jobStatus(item *batchv1.Job) string {
status := v1alpha2.StatusFailed
if item.Status.Active > 0 {
status = v1alpha2.StatusRunning
} else if item.Status.Failed > 0 {
status = v1alpha2.StatusFailed
} else if item.Status.Succeeded > 0 {
status = v1alpha2.StatusComplete
}
return status
}
func (*jobSearcher) match(match map[string]string, item *batchv1.Job) bool {
for k, v := range match {
switch k {
case v1alpha2.Status:
if jobStatus(item) != v {
return false
}
case includeCronJob:
if v == "false" && k8sutil.IsControlledBy(item.OwnerReferences, cronJobKind, "") {
return false
}
case includeS2iRun:
if v == "false" && k8sutil.IsControlledBy(item.OwnerReferences, s2iRunKind, "") {
return false
}
default:
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
}
return true
}
func (*jobSearcher) fuzzy(fuzzy map[string]string, item *batchv1.Job) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func jobUpdateTime(item *batchv1.Job) time.Time {
updateTime := item.CreationTimestamp.Time
for _, condition := range item.Status.Conditions {
if updateTime.Before(condition.LastProbeTime.Time) {
updateTime = condition.LastProbeTime.Time
}
if updateTime.Before(condition.LastTransitionTime.Time) {
updateTime = condition.LastTransitionTime.Time
}
}
return updateTime
}
func (*jobSearcher) compare(left, right *batchv1.Job, orderBy string) bool {
switch orderBy {
case v1alpha2.UpdateTime:
return jobUpdateTime(left).Before(jobUpdateTime(right))
default:
return v1alpha2.ObjectMetaCompare(left.ObjectMeta, right.ObjectMeta, orderBy)
}
}
func (s *jobSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
jobs, err := s.informers.Batch().V1().Jobs().Lister().Jobs(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*batchv1.Job, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = jobs
} else {
for _, item := range jobs {
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 s.compare(result[i], result[j], orderBy)
})
r := make([]interface{}, 0)
for _, i := range result {
r = append(r, i)
}
return r, nil
}

View File

@@ -1,92 +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 namespace
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"sort"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params"
)
type namespaceSearcher struct {
informers informers.SharedInformerFactory
}
func NewNamespaceSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &namespaceSearcher{informers: informers}
}
func (s *namespaceSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Core().V1().Namespaces().Lister().Get(name)
}
func (*namespaceSearcher) match(match map[string]string, item *v1.Namespace) bool {
for k, v := range match {
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (*namespaceSearcher) fuzzy(fuzzy map[string]string, item *v1.Namespace) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *namespaceSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
namespaces, err := s.informers.Core().V1().Namespaces().Lister().List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1.Namespace, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = namespaces
} else {
for _, item := range namespaces {
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
}

View File

@@ -1,142 +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 node
import (
"fmt"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"sort"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params"
)
const (
nodeConfigOK v1.NodeConditionType = "ConfigOK"
nodeKubeletReady v1.NodeConditionType = "KubeletReady"
)
type nodeSearcher struct {
informers informers.SharedInformerFactory
}
func NewNodeSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &nodeSearcher{informers: informers}
}
func (s *nodeSearcher) Get(_, name string) (interface{}, error) {
return s.informers.Core().V1().Nodes().Lister().Get(name)
}
func getNodeStatus(node *v1.Node) string {
if node.Spec.Unschedulable {
return v1alpha2.StatusUnschedulable
}
for _, condition := range node.Status.Conditions {
if isUnhealthyStatus(condition) {
return v1alpha2.StatusWarning
}
}
return v1alpha2.StatusRunning
}
var expectedConditions = map[v1.NodeConditionType]v1.ConditionStatus{
v1.NodeMemoryPressure: v1.ConditionFalse,
v1.NodeDiskPressure: v1.ConditionFalse,
v1.NodePIDPressure: v1.ConditionFalse,
v1.NodeNetworkUnavailable: v1.ConditionFalse,
nodeConfigOK: v1.ConditionTrue,
nodeKubeletReady: v1.ConditionTrue,
v1.NodeReady: v1.ConditionTrue,
}
func isUnhealthyStatus(condition v1.NodeCondition) bool {
expectedStatus := expectedConditions[condition.Type]
if expectedStatus != "" && condition.Status != expectedStatus {
return true
}
return false
}
func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool {
for k, v := range match {
switch k {
case v1alpha2.Role:
labelKey := fmt.Sprintf("node-role.kubernetes.io/%s", v)
if _, ok := item.Labels[labelKey]; !ok {
return false
}
case v1alpha2.Status:
if getNodeStatus(item) != v {
return false
}
default:
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
}
return true
}
func (*nodeSearcher) fuzzy(fuzzy map[string]string, item *v1.Node) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *nodeSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
nodes, err := s.informers.Core().V1().Nodes().Lister().List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1.Node, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = nodes
} else {
for _, item := range nodes {
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
}

View File

@@ -1,169 +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 persistentvolumeclaim
import (
"strconv"
snapshotinformer "github.com/kubernetes-csi/external-snapshotter/client/v4/informers/externalversions"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"sort"
"strings"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels"
)
const (
storageClassName = "storageClassName"
)
type persistentVolumeClaimSearcher struct {
informers informers.SharedInformerFactory
snapshotInformers snapshotinformer.SharedInformerFactory
}
func NewPersistentVolumeClaimSearcher(informers informers.SharedInformerFactory, snapshotInformer snapshotinformer.SharedInformerFactory) v1alpha2.Interface {
return &persistentVolumeClaimSearcher{
informers: informers,
snapshotInformers: snapshotInformer,
}
}
func (s *persistentVolumeClaimSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Core().V1().PersistentVolumeClaims().Lister().PersistentVolumeClaims(namespace).Get(name)
}
func pvcStatus(item *v1.PersistentVolumeClaim) string {
status := v1alpha2.StatusPending
if item.Status.Phase == v1.ClaimPending {
status = v1alpha2.StatusPending
} else if item.Status.Phase == v1.ClaimBound {
status = v1alpha2.StatusBound
} else if item.Status.Phase == v1.ClaimLost {
status = v1alpha2.StatusLost
}
return status
}
func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.PersistentVolumeClaim) bool {
for k, v := range match {
switch k {
case v1alpha2.Status:
statuses := strings.Split(v, "|")
if !sliceutil.HasString(statuses, pvcStatus(item)) {
return false
}
case storageClassName:
if item.Spec.StorageClassName == nil || *item.Spec.StorageClassName != v {
return false
}
default:
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
}
return true
}
func (*persistentVolumeClaimSearcher) fuzzy(fuzzy map[string]string, item *v1.PersistentVolumeClaim) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *persistentVolumeClaimSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
persistentVolumeClaims, err := s.informers.Core().V1().PersistentVolumeClaims().Lister().PersistentVolumeClaims(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1.PersistentVolumeClaim, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = persistentVolumeClaims
} else {
for _, item := range persistentVolumeClaims {
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 {
i = i.DeepCopy()
inUse := s.countPods(i.Name, i.Namespace)
isSnapshotAllow := s.isSnapshotAllowed(i.GetAnnotations()["volume.beta.kubernetes.io/storage-provisioner"])
if i.Annotations == nil {
i.Annotations = make(map[string]string)
}
i.Annotations["kubesphere.io/in-use"] = strconv.FormatBool(inUse)
i.Annotations["kubesphere.io/allow-snapshot"] = strconv.FormatBool(isSnapshotAllow)
r = append(r, i)
}
return r, nil
}
func (s *persistentVolumeClaimSearcher) countPods(name, namespace string) bool {
pods, err := s.informers.Core().V1().Pods().Lister().Pods(namespace).List(labels.Everything())
if err != nil {
return false
}
for _, pod := range pods {
for _, pvc := range pod.Spec.Volumes {
if pvc.PersistentVolumeClaim != nil && pvc.PersistentVolumeClaim.ClaimName == name {
return true
}
}
}
return false
}
func (s *persistentVolumeClaimSearcher) isSnapshotAllowed(provisioner string) bool {
if len(provisioner) == 0 {
return false
}
volumeSnapshotClasses, err := s.snapshotInformers.Snapshot().V1beta1().VolumeSnapshotClasses().Lister().List(labels.Everything())
if err != nil {
return false
}
for _, volumeSnapshotClass := range volumeSnapshotClasses {
if volumeSnapshotClass.Driver == provisioner {
return true
}
}
return false
}

View File

@@ -1,240 +0,0 @@
package persistentvolumeclaim
import (
"testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
"github.com/google/go-cmp/cmp"
snapshot "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
snapshotefakeclient "github.com/kubernetes-csi/external-snapshotter/client/v4/clientset/versioned/fake"
snapshotinformers "github.com/kubernetes-csi/external-snapshotter/client/v4/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
)
var (
testStorageClassName = "sc1"
)
var (
pvc1 = &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "pvc-1",
Namespace: "default",
Annotations: map[string]string{
"kubesphere.io/in-use": "false",
"kubesphere.io/allow-snapshot": "false",
},
},
Spec: corev1.PersistentVolumeClaimSpec{
StorageClassName: &testStorageClassName,
},
Status: corev1.PersistentVolumeClaimStatus{
Phase: corev1.ClaimPending,
},
}
pvc2 = &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "pvc-2",
Namespace: "default",
Annotations: map[string]string{
"kubesphere.io/in-use": "false",
"kubesphere.io/allow-snapshot": "false",
},
},
Spec: corev1.PersistentVolumeClaimSpec{
StorageClassName: &testStorageClassName,
},
Status: corev1.PersistentVolumeClaimStatus{
Phase: corev1.ClaimLost,
},
}
pvc3 = &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "pvc-3",
Namespace: "default",
Annotations: map[string]string{
"kubesphere.io/in-use": "true",
"kubesphere.io/allow-snapshot": "false",
},
},
Spec: corev1.PersistentVolumeClaimSpec{
StorageClassName: &testStorageClassName,
},
Status: corev1.PersistentVolumeClaimStatus{
Phase: corev1.ClaimBound,
},
}
pod1 = &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod-1",
Namespace: "default",
},
Spec: corev1.PodSpec{
Volumes: []corev1.Volume{
{
Name: "data",
VolumeSource: corev1.VolumeSource{
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
ClaimName: pvc3.Name,
},
},
},
},
},
}
vsc1 = &snapshot.VolumeSnapshotClass{
ObjectMeta: metav1.ObjectMeta{
Name: "VolumeSnapshotClass-1",
Namespace: "default",
},
Driver: testStorageClassName,
}
persistentVolumeClaims = []interface{}{pvc1, pvc2, pvc3}
pods = []interface{}{pod1}
volumeSnapshotClasses = []interface{}{vsc1}
)
func prepare() (v1alpha2.Interface, error) {
client := fake.NewSimpleClientset()
informer := informers.NewSharedInformerFactory(client, 0)
snapshotClient := snapshotefakeclient.NewSimpleClientset()
snapshotInformers := snapshotinformers.NewSharedInformerFactory(snapshotClient, 0)
for _, persistentVolumeClaim := range persistentVolumeClaims {
err := informer.Core().V1().PersistentVolumeClaims().Informer().GetIndexer().Add(persistentVolumeClaim)
if err != nil {
return nil, err
}
}
for _, pod := range pods {
err := informer.Core().V1().Pods().Informer().GetIndexer().Add(pod)
if err != nil {
return nil, err
}
}
for _, volumeSnapshotClass := range volumeSnapshotClasses {
err := snapshotInformers.Snapshot().V1().VolumeSnapshotClasses().Informer().GetIndexer().Add(volumeSnapshotClass)
if err != nil {
return nil, err
}
}
return NewPersistentVolumeClaimSearcher(informer, snapshotInformers), nil
}
func TestGet(t *testing.T) {
tests := []struct {
Namespace string
Name string
Expected interface{}
ExpectedErr error
}{
{
"default",
"pvc-1",
pvc1,
nil,
},
}
getter, err := prepare()
if err != nil {
t.Fatal(err)
}
for _, test := range tests {
got, err := getter.Get(test.Namespace, test.Name)
if test.ExpectedErr != nil && err != test.ExpectedErr {
t.Errorf("expected error, got nothing")
} else if err != nil {
t.Fatal(err)
}
diff := cmp.Diff(got, test.Expected)
if diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.Expected, diff)
}
}
}
func TestSearch(t *testing.T) {
tests := []struct {
Namespace string
Conditions *params.Conditions
OrderBy string
Reverse bool
Expected []interface{}
ExpectedErr error
}{
{
Namespace: "default",
Conditions: &params.Conditions{
Match: map[string]string{
v1alpha2.Status: v1alpha2.StatusPending,
},
Fuzzy: nil,
},
OrderBy: "name",
Reverse: false,
Expected: []interface{}{pvc1},
ExpectedErr: nil,
},
{
Namespace: "default",
Conditions: &params.Conditions{
Match: map[string]string{
v1alpha2.Status: v1alpha2.StatusLost,
},
Fuzzy: nil,
},
OrderBy: "name",
Reverse: false,
Expected: []interface{}{pvc2},
ExpectedErr: nil,
},
{
Namespace: "default",
Conditions: &params.Conditions{
Match: map[string]string{
v1alpha2.Status: v1alpha2.StatusBound,
},
Fuzzy: nil,
},
OrderBy: "name",
Reverse: false,
Expected: []interface{}{pvc3},
ExpectedErr: nil,
},
}
searcher, err := prepare()
if err != nil {
t.Fatal(err)
}
for _, test := range tests {
got, err := searcher.Search(test.Namespace, test.Conditions, test.OrderBy, test.Reverse)
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, test.Expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.Expected, diff)
}
}
}

View File

@@ -1,241 +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 pod
import (
appsv1 "k8s.io/api/apps/v1"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"sort"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params"
)
type podSearcher struct {
informers informers.SharedInformerFactory
}
func NewPodSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &podSearcher{informers: informers}
}
func (s *podSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Core().V1().Pods().Lister().Pods(namespace).Get(name)
}
func (s *podSearcher) podBelongTo(item *v1.Pod, kind string, name string) bool {
switch kind {
case "Deployment":
if s.podBelongToDeployment(item, name) {
return true
}
case "ReplicaSet":
if podBelongToReplicaSet(item, name) {
return true
}
case "DaemonSet":
if podBelongToDaemonSet(item, name) {
return true
}
case "StatefulSet":
if podBelongToStatefulSet(item, name) {
return true
}
case "Job":
if podBelongToJob(item, name) {
return true
}
}
return false
}
func replicaSetBelongToDeployment(replicaSet *appsv1.ReplicaSet, deploymentName string) bool {
for _, owner := range replicaSet.OwnerReferences {
if owner.Kind == "Deployment" && owner.Name == deploymentName {
return true
}
}
return false
}
func podBelongToDaemonSet(item *v1.Pod, name string) bool {
for _, owner := range item.OwnerReferences {
if owner.Kind == "DaemonSet" && owner.Name == name {
return true
}
}
return false
}
func podBelongToJob(item *v1.Pod, name string) bool {
for _, owner := range item.OwnerReferences {
if owner.Kind == "Job" && owner.Name == name {
return true
}
}
return false
}
func podBelongToReplicaSet(item *v1.Pod, replicaSetName string) bool {
for _, owner := range item.OwnerReferences {
if owner.Kind == "ReplicaSet" && owner.Name == replicaSetName {
return true
}
}
return false
}
func podBelongToStatefulSet(item *v1.Pod, statefulSetName string) bool {
for _, owner := range item.OwnerReferences {
if owner.Kind == "StatefulSet" && owner.Name == statefulSetName {
return true
}
}
return false
}
func (s *podSearcher) podBelongToDeployment(item *v1.Pod, deploymentName string) bool {
replicas, err := s.informers.Apps().V1().ReplicaSets().Lister().ReplicaSets(item.Namespace).List(labels.Everything())
if err != nil {
return false
}
for _, r := range replicas {
if replicaSetBelongToDeployment(r, deploymentName) && podBelongToReplicaSet(item, r.Name) {
return true
}
}
return false
}
func podBindPVC(item *v1.Pod, pvcName string) bool {
for _, v := range item.Spec.Volumes {
if v.VolumeSource.PersistentVolumeClaim != nil &&
v.VolumeSource.PersistentVolumeClaim.ClaimName == pvcName {
return true
}
}
return false
}
func (s *podSearcher) podBelongToService(item *v1.Pod, serviceName string) bool {
service, err := s.informers.Core().V1().Services().Lister().Services(item.Namespace).Get(serviceName)
if err != nil {
return false
}
selector := labels.Set(service.Spec.Selector).AsSelectorPreValidated()
if selector.Empty() || !selector.Matches(labels.Set(item.Labels)) {
return false
}
return true
}
func (s *podSearcher) match(match map[string]string, item *v1.Pod) bool {
for k, v := range match {
switch k {
case v1alpha2.OwnerKind:
fallthrough
case v1alpha2.OwnerName:
kind := match[v1alpha2.OwnerKind]
name := match[v1alpha2.OwnerName]
if !s.podBelongTo(item, kind, name) {
return false
}
case "nodeName":
if item.Spec.NodeName != v {
return false
}
case "pvcName":
if !podBindPVC(item, v) {
return false
}
case "serviceName":
if !s.podBelongToService(item, v) {
return false
}
default:
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
}
return true
}
func (*podSearcher) fuzzy(fuzzy map[string]string, item *v1.Pod) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (*podSearcher) compare(left, right *v1.Pod, orderBy string) bool {
switch orderBy {
case v1alpha2.StartTime:
if left.Status.StartTime == nil {
return false
}
if right.Status.StartTime == nil {
return true
}
return left.Status.StartTime.Before(right.Status.StartTime)
default:
return v1alpha2.ObjectMetaCompare(left.ObjectMeta, right.ObjectMeta, orderBy)
}
}
func (s *podSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
pods, err := s.informers.Core().V1().Pods().Lister().Pods(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1.Pod, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = pods
} else {
for _, item := range pods {
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 s.compare(result[i], result[j], orderBy)
})
r := make([]interface{}, 0)
for _, i := range result {
r = append(r, i)
}
return r, nil
}

View File

@@ -1,236 +0,0 @@
/*
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 resource
import (
"testing"
"github.com/google/go-cmp/cmp"
fakesnapshot "github.com/kubernetes-csi/external-snapshotter/client/v4/clientset/versioned/fake"
fakeistio "istio.io/client-go/pkg/clientset/versioned/fake"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
fakek8s "k8s.io/client-go/kubernetes/fake"
fakeks "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
)
func TestConditions(t *testing.T) {
factory, err := prepare()
if err != nil {
t.Fatal(err)
}
resource := NewResourceGetter(factory)
tests := []struct {
Name string
Namespace string
Resource string
Conditions *params.Conditions
OrderBy string
Reverse bool
Limit int
Offset int
ExpectResponse *models.PageableResponse
ExpectError error
}{{
Name: "list namespace order by name asc",
Namespace: "",
Resource: "namespaces",
Conditions: &params.Conditions{},
OrderBy: "name",
Reverse: false,
Limit: 10,
Offset: 0,
ExpectResponse: &models.PageableResponse{
Items: []interface{}{defaultNamespace, kubesphereNamespace},
TotalCount: 2,
},
ExpectError: nil,
}, {
Name: "list namespace order by name desc",
Namespace: "",
Resource: "namespaces",
Conditions: &params.Conditions{},
OrderBy: "name",
Reverse: true,
Limit: 10,
Offset: 0,
ExpectResponse: &models.PageableResponse{
Items: []interface{}{kubesphereNamespace, defaultNamespace},
TotalCount: 2,
},
ExpectError: nil,
},
{
Name: "list deployment",
Namespace: "default",
Resource: "deployments",
Conditions: &params.Conditions{},
OrderBy: "name",
Reverse: false,
Limit: 10,
Offset: 0,
ExpectResponse: &models.PageableResponse{
Items: []interface{}{nginxDeployment, redisDeployment},
TotalCount: 2,
},
ExpectError: nil,
},
{
Name: "filter deployment by keyword",
Namespace: "default",
Resource: "deployments",
Conditions: &params.Conditions{
Match: map[string]string{v1alpha2.Keyword: "ngin"},
Fuzzy: nil,
},
OrderBy: "name",
Reverse: true,
Limit: 10,
Offset: 0,
ExpectResponse: &models.PageableResponse{
Items: []interface{}{nginxDeployment},
TotalCount: 1,
},
ExpectError: nil,
},
{
Name: "filter deployment by label",
Namespace: "default",
Resource: "deployments",
Conditions: &params.Conditions{
Match: map[string]string{"kubesphere.io/creator": "admin"},
Fuzzy: nil,
},
OrderBy: "",
Reverse: true,
Limit: 10,
Offset: 0,
ExpectResponse: &models.PageableResponse{
Items: []interface{}{redisDeployment},
TotalCount: 1,
},
ExpectError: nil,
}, {
Name: "filter deployment by status",
Namespace: "default",
Resource: "deployments",
Conditions: &params.Conditions{
Match: map[string]string{v1alpha2.Status: v1alpha2.StatusRunning},
Fuzzy: nil,
},
OrderBy: "",
Reverse: true,
Limit: 10,
Offset: 0,
ExpectResponse: &models.PageableResponse{
Items: []interface{}{nginxDeployment},
TotalCount: 1,
},
ExpectError: nil,
},
}
for _, test := range tests {
response, err := resource.ListResources(test.Namespace, test.Resource, test.Conditions, test.OrderBy, test.Reverse, test.Limit, test.Offset)
if err != test.ExpectError {
t.Fatalf("expected error: %s, got: %s", test.ExpectError, err)
}
if diff := cmp.Diff(test.ExpectResponse, response); diff != "" {
t.Errorf(diff)
}
}
}
var (
defaultNamespace = &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
Labels: map[string]string{"kubesphere.io/workspace": "system-workspace"},
},
}
kubesphereNamespace = &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "kubesphere-system",
Labels: map[string]string{"kubesphere.io/workspace": "system-workspace"},
},
}
replicas = int32(1)
nginxDeployment = &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "nginx",
Namespace: "default",
},
Spec: appsv1.DeploymentSpec{
Replicas: &replicas,
},
Status: appsv1.DeploymentStatus{
ReadyReplicas: 1,
},
}
redisDeployment = &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "redis",
Namespace: "default",
Labels: map[string]string{"kubesphere.io/creator": "admin"},
},
Spec: appsv1.DeploymentSpec{
Replicas: &replicas,
},
Status: appsv1.DeploymentStatus{
ReadyReplicas: 0,
},
}
)
func prepare() (informers.InformerFactory, error) {
namespaces := []interface{}{defaultNamespace, kubesphereNamespace}
deployments := []interface{}{nginxDeployment, redisDeployment}
ksClient := fakeks.NewSimpleClientset()
k8sClient := fakek8s.NewSimpleClientset()
istioClient := fakeistio.NewSimpleClientset()
snapshotClient := fakesnapshot.NewSimpleClientset()
fakeInformerFactory := informers.NewInformerFactories(k8sClient, ksClient, istioClient, snapshotClient, nil, nil)
k8sInformerFactory := fakeInformerFactory.KubernetesSharedInformerFactory()
for _, namespace := range namespaces {
err := k8sInformerFactory.Core().V1().Namespaces().Informer().GetIndexer().Add(namespace)
if err != nil {
return nil, err
}
}
for _, deployment := range deployments {
err := k8sInformerFactory.Apps().V1().Deployments().Informer().GetIndexer().Add(deployment)
if err != nil {
return nil, err
}
}
return fakeInformerFactory, nil
}

View File

@@ -1,143 +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 resource
import (
"errors"
"k8s.io/klog/v2"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/clusterrole"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/configmap"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/cronjob"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/daemonset"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/deployment"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/hpa"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/ingress"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/job"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/namespace"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/node"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/persistentvolumeclaim"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/pod"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/role"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/s2buildertemplate"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/s2ibuilder"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/s2irun"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/secret"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/service"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/statefulset"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/storageclass"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/workspace"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
)
var ErrResourceNotSupported = errors.New("resource is not supported")
type ResourceGetter struct {
resourcesGetters map[string]v1alpha2.Interface
}
func (r ResourceGetter) Add(resource string, getter v1alpha2.Interface) {
if r.resourcesGetters == nil {
r.resourcesGetters = make(map[string]v1alpha2.Interface)
}
r.resourcesGetters[resource] = getter
}
func NewResourceGetter(factory informers.InformerFactory) *ResourceGetter {
resourceGetters := make(map[string]v1alpha2.Interface)
resourceGetters[v1alpha2.ConfigMaps] = configmap.NewConfigmapSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.CronJobs] = cronjob.NewCronJobSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.DaemonSets] = daemonset.NewDaemonSetSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.Deployments] = deployment.NewDeploymentSetSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.Ingresses] = ingress.NewIngressSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.Jobs] = job.NewJobSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.PersistentVolumeClaims] = persistentvolumeclaim.NewPersistentVolumeClaimSearcher(factory.KubernetesSharedInformerFactory(), factory.SnapshotSharedInformerFactory())
resourceGetters[v1alpha2.Secrets] = secret.NewSecretSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.Services] = service.NewServiceSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.StatefulSets] = statefulset.NewStatefulSetSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.Pods] = pod.NewPodSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.Roles] = role.NewRoleSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.Nodes] = node.NewNodeSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.Namespaces] = namespace.NewNamespaceSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.ClusterRoles] = clusterrole.NewClusterRoleSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.StorageClasses] = storageclass.NewStorageClassesSearcher(factory.KubernetesSharedInformerFactory(), factory.SnapshotSharedInformerFactory())
resourceGetters[v1alpha2.HorizontalPodAutoscalers] = hpa.NewHpaSearcher(factory.KubernetesSharedInformerFactory())
resourceGetters[v1alpha2.S2iBuilders] = s2ibuilder.NewS2iBuilderSearcher(factory.KubeSphereSharedInformerFactory())
resourceGetters[v1alpha2.S2iRuns] = s2irun.NewS2iRunSearcher(factory.KubeSphereSharedInformerFactory())
resourceGetters[v1alpha2.S2iBuilderTemplates] = s2buildertemplate.NewS2iBuidlerTemplateSearcher(factory.KubeSphereSharedInformerFactory())
resourceGetters[v1alpha2.Workspaces] = workspace.NewWorkspaceSearcher(factory.KubeSphereSharedInformerFactory())
return &ResourceGetter{resourcesGetters: resourceGetters}
}
var (
clusterResources = []string{v1alpha2.Nodes, v1alpha2.Workspaces, v1alpha2.Namespaces, v1alpha2.ClusterRoles, v1alpha2.StorageClasses, v1alpha2.S2iBuilderTemplates}
)
func (r *ResourceGetter) GetResource(namespace, resource, name string) (interface{}, error) {
// none namespace resource
if namespace != "" && sliceutil.HasString(clusterResources, resource) {
return nil, ErrResourceNotSupported
}
if searcher, ok := r.resourcesGetters[resource]; ok {
resource, err := searcher.Get(namespace, name)
if err != nil {
klog.Error(err)
return nil, err
}
return resource, nil
}
return nil, ErrResourceNotSupported
}
func (r *ResourceGetter) ListResources(namespace, resource string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
var items []interface{}
var err error
var result []interface{}
// none namespace resource
if namespace != "" && sliceutil.HasString(clusterResources, resource) {
return nil, ErrResourceNotSupported
}
if searcher, ok := r.resourcesGetters[resource]; ok {
result, err = searcher.Search(namespace, conditions, orderBy, reverse)
} else {
return nil, ErrResourceNotSupported
}
if err != nil {
klog.Error(err)
return nil, err
}
if limit == -1 || limit+offset > len(result) {
limit = len(result) - offset
}
items = result[offset : offset+limit]
return &models.PageableResponse{TotalCount: len(result), Items: items}, nil
}

View File

@@ -1,107 +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 role
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"sort"
rbac "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params"
)
type roleSearcher struct {
informers informers.SharedInformerFactory
}
func NewRoleSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &roleSearcher{informers: informers}
}
func (s *roleSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Rbac().V1().Roles().Lister().Roles(namespace).Get(name)
}
func (*roleSearcher) match(match map[string]string, item *rbac.Role) bool {
for k, v := range match {
switch k {
case v1alpha2.UserFacing:
if v == "true" {
if !isUserFacingRole(item) {
return false
}
}
default:
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
}
return true
}
func (*roleSearcher) fuzzy(fuzzy map[string]string, item *rbac.Role) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *roleSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
roles, err := s.informers.Rbac().V1().Roles().Lister().Roles(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*rbac.Role, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = roles
} else {
for _, item := range roles {
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
}
// role created by user from kubesphere dashboard
func isUserFacingRole(role *rbac.Role) bool {
return role.Annotations[constants.CreatorAnnotationKey] != ""
}

View File

@@ -1,92 +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 s2buildertemplate
import (
"kubesphere.io/api/devops/v1alpha1"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"sort"
"k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params"
)
type s2iBuilderTemplateSearcher struct {
informers externalversions.SharedInformerFactory
}
func NewS2iBuidlerTemplateSearcher(informers externalversions.SharedInformerFactory) v1alpha2.Interface {
return &s2iBuilderTemplateSearcher{informers: informers}
}
func (s *s2iBuilderTemplateSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Devops().V1alpha1().S2iBuilderTemplates().Lister().Get(name)
}
func (*s2iBuilderTemplateSearcher) match(match map[string]string, item *v1alpha1.S2iBuilderTemplate) bool {
for k, v := range match {
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (*s2iBuilderTemplateSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iBuilderTemplate) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *s2iBuilderTemplateSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
builderTemplates, err := s.informers.Devops().V1alpha1().S2iBuilderTemplates().Lister().List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1alpha1.S2iBuilderTemplate, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = builderTemplates
} else {
for _, item := range builderTemplates {
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
}

View File

@@ -1,92 +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 s2ibuilder
import (
"k8s.io/apimachinery/pkg/labels"
"kubesphere.io/api/devops/v1alpha1"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"sort"
"kubesphere.io/kubesphere/pkg/server/params"
)
type s2iBuilderSearcher struct {
informers externalversions.SharedInformerFactory
}
func NewS2iBuilderSearcher(informers externalversions.SharedInformerFactory) v1alpha2.Interface {
return &s2iBuilderSearcher{informers: informers}
}
func (s *s2iBuilderSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Devops().V1alpha1().S2iBuilders().Lister().S2iBuilders(namespace).Get(name)
}
func (*s2iBuilderSearcher) match(match map[string]string, item *v1alpha1.S2iBuilder) bool {
for k, v := range match {
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (*s2iBuilderSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iBuilder) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *s2iBuilderSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
s2iBuilders, err := s.informers.Devops().V1alpha1().S2iBuilders().Lister().S2iBuilders(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1alpha1.S2iBuilder, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = s2iBuilders
} else {
for _, item := range s2iBuilders {
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
}

View File

@@ -1,98 +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 s2irun
import (
"sort"
"k8s.io/apimachinery/pkg/labels"
"kubesphere.io/api/devops/v1alpha1"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
)
type s2iRunSearcher struct {
informers externalversions.SharedInformerFactory
}
func NewS2iRunSearcher(informers externalversions.SharedInformerFactory) v1alpha2.Interface {
return &s2iRunSearcher{informers: informers}
}
func (s *s2iRunSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Devops().V1alpha1().S2iRuns().Lister().S2iRuns(namespace).Get(name)
}
func (*s2iRunSearcher) match(match map[string]string, item *v1alpha1.S2iRun) bool {
for k, v := range match {
switch k {
case v1alpha2.Status:
if string(item.Status.RunState) != v {
return false
}
default:
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
}
return true
}
func (*s2iRunSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iRun) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *s2iRunSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
s2iRuns, err := s.informers.Devops().V1alpha1().S2iRuns().Lister().S2iRuns(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1alpha1.S2iRun, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = s2iRuns
} else {
for _, item := range s2iRuns {
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
}

View File

@@ -1,99 +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 secret
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"sort"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params"
)
type secretSearcher struct {
informers informers.SharedInformerFactory
}
func NewSecretSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &secretSearcher{informers: informers}
}
func (s *secretSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Core().V1().Secrets().Lister().Secrets(namespace).Get(name)
}
func (*secretSearcher) match(match map[string]string, item *v1.Secret) bool {
for k, v := range match {
switch k {
case "type":
if string(item.Type) != v {
return false
}
default:
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
}
return true
}
func (*secretSearcher) fuzzy(fuzzy map[string]string, item *v1.Secret) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *secretSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
secrets, err := s.informers.Core().V1().Secrets().Lister().Secrets(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1.Secret, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = secrets
} else {
for _, item := range secrets {
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
}

View File

@@ -1,92 +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 service
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"sort"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params"
)
type serviceSearcher struct {
informers informers.SharedInformerFactory
}
func NewServiceSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &serviceSearcher{informers: informers}
}
func (s *serviceSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Core().V1().Services().Lister().Services(namespace).Get(name)
}
func (*serviceSearcher) match(match map[string]string, item *v1.Service) bool {
for k, v := range match {
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (*serviceSearcher) fuzzy(fuzzy map[string]string, item *v1.Service) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *serviceSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
services, err := s.informers.Core().V1().Services().Lister().Services(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1.Service, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = services
} else {
for _, item := range services {
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
}

View File

@@ -1,112 +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 statefulset
import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"sort"
v1 "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params"
)
type statefulSetSearcher struct {
informers informers.SharedInformerFactory
}
func NewStatefulSetSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return &statefulSetSearcher{informers: informers}
}
func (s *statefulSetSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Apps().V1().StatefulSets().Lister().StatefulSets(namespace).Get(name)
}
func statefulSetStatus(item *v1.StatefulSet) string {
if item.Spec.Replicas != nil {
if item.Status.ReadyReplicas == 0 && *item.Spec.Replicas == 0 {
return v1alpha2.StatusStopped
} else if item.Status.ReadyReplicas == *item.Spec.Replicas {
return v1alpha2.StatusRunning
} else {
return v1alpha2.StatusUpdating
}
}
return v1alpha2.StatusStopped
}
func (*statefulSetSearcher) match(match map[string]string, item *v1.StatefulSet) bool {
for k, v := range match {
switch k {
case v1alpha2.Status:
if statefulSetStatus(item) != v {
return false
}
default:
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
}
return true
}
func (*statefulSetSearcher) fuzzy(fuzzy map[string]string, item *v1.StatefulSet) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *statefulSetSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
statefulSets, err := s.informers.Apps().V1().StatefulSets().Lister().StatefulSets(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1.StatefulSet, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = statefulSets
} else {
for _, item := range statefulSets {
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
}

View File

@@ -1,119 +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 storageclass
import (
"sort"
"strconv"
snapshotinformer "github.com/kubernetes-csi/external-snapshotter/client/v4/informers/externalversions"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/storage/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
)
type storageClassesSearcher struct {
informers informers.SharedInformerFactory
snapshotInformers snapshotinformer.SharedInformerFactory
}
func NewStorageClassesSearcher(informers informers.SharedInformerFactory, snapshotInformer snapshotinformer.SharedInformerFactory) v1alpha2.Interface {
return &storageClassesSearcher{
informers: informers,
snapshotInformers: snapshotInformer,
}
}
func (s *storageClassesSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Storage().V1().StorageClasses().Lister().Get(name)
}
func (*storageClassesSearcher) match(match map[string]string, item *v1.StorageClass) bool {
for k, v := range match {
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (*storageClassesSearcher) fuzzy(fuzzy map[string]string, item *v1.StorageClass) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *storageClassesSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
storageClasses, err := s.informers.Storage().V1().StorageClasses().Lister().List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1.StorageClass, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = storageClasses
} else {
for _, item := range storageClasses {
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 {
i = i.DeepCopy()
count := s.countPersistentVolumeClaims(i.Name)
if i.Annotations == nil {
i.Annotations = make(map[string]string)
}
i.Annotations["kubesphere.io/pvc-count"] = strconv.Itoa(count)
r = append(r, i)
}
return r, nil
}
func (s *storageClassesSearcher) countPersistentVolumeClaims(name string) int {
pvcs, err := s.informers.Core().V1().PersistentVolumeClaims().Lister().List(labels.Everything())
if err != nil {
return 0
}
var count int
for _, pvc := range pvcs {
if (pvc.Spec.StorageClassName != nil && *pvc.Spec.StorageClassName == name) || (pvc.Annotations != nil && pvc.Annotations[corev1.BetaStorageClassAnnotation] == name) {
count++
}
}
return count
}

View File

@@ -1,135 +0,0 @@
// Copyright 2022 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 storageclass
import (
"testing"
"github.com/google/go-cmp/cmp"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/storage/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
"k8s.io/utils/pointer"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
)
var (
sc1 = &v1.StorageClass{
ObjectMeta: metav1.ObjectMeta{
Name: "sc1",
},
}
sc1Expected = &v1.StorageClass{
ObjectMeta: metav1.ObjectMeta{
Name: "sc1",
Annotations: map[string]string{
"kubesphere.io/pvc-count": "1",
},
},
}
scs = []interface{}{sc1}
scsExpected = []interface{}{sc1Expected}
pvc1 = &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "pvc1",
Namespace: "default",
},
Spec: corev1.PersistentVolumeClaimSpec{
VolumeName: "pvc1-volume",
StorageClassName: pointer.StringPtr("sc1"),
},
}
pvc2 = &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "pvc2",
Namespace: "default",
},
Spec: corev1.PersistentVolumeClaimSpec{
VolumeName: "pvc2-volume",
},
}
pvcs = []interface{}{pvc1, pvc2}
)
func prepare() (v1alpha2.Interface, error) {
client := fake.NewSimpleClientset()
informer := informers.NewSharedInformerFactory(client, 0)
for _, sc := range scs {
err := informer.Storage().V1().StorageClasses().Informer().GetIndexer().Add(sc)
if err != nil {
return nil, err
}
}
for _, pvc := range pvcs {
err := informer.Core().V1().PersistentVolumeClaims().Informer().GetIndexer().Add(pvc)
if err != nil {
return nil, err
}
}
return NewStorageClassesSearcher(informer, nil), nil
}
func TestSearch(t *testing.T) {
tests := []struct {
namespace string
name string
conditions *params.Conditions
orderBy string
reverse bool
expected interface{}
expectedErr error
}{
{
namespace: "default",
name: sc1.Name,
conditions: &params.Conditions{},
orderBy: "name",
reverse: true,
expected: scsExpected,
expectedErr: nil,
},
}
searcher, err := prepare()
if err != nil {
t.Fatal(err)
}
for _, test := range tests {
got, err := searcher.Search(test.namespace, test.conditions, test.orderBy, test.reverse)
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, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
}
}
}

View File

@@ -1,93 +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 workspace
import (
tenantv1alpha1 "kubesphere.io/api/tenant/v1alpha1"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"sort"
"k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/server/params"
)
type workspaceSearcher struct {
informers externalversions.SharedInformerFactory
}
func NewWorkspaceSearcher(informers externalversions.SharedInformerFactory) v1alpha2.Interface {
return &workspaceSearcher{informers: informers}
}
func (s *workspaceSearcher) Get(namespace, name string) (interface{}, error) {
return s.informers.Tenant().V1alpha1().Workspaces().Lister().Get(name)
}
func (*workspaceSearcher) match(match map[string]string, item *tenantv1alpha1.Workspace) bool {
for k, v := range match {
if !v1alpha2.ObjectMetaExactlyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (*workspaceSearcher) fuzzy(fuzzy map[string]string, item *tenantv1alpha1.Workspace) bool {
for k, v := range fuzzy {
if !v1alpha2.ObjectMetaFuzzyMath(k, v, item.ObjectMeta) {
return false
}
}
return true
}
func (s *workspaceSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
workspaces, err := s.informers.Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*tenantv1alpha1.Workspace, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = workspaces
} else {
for _, item := range workspaces {
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
}

View File

@@ -1,106 +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 (
"context"
"time"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog/v2"
appv1beta1 "sigs.k8s.io/application/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type applicationsGetter struct {
c cache.Cache
}
func New(c cache.Cache) v1alpha3.Interface {
return &applicationsGetter{c}
}
func (d *applicationsGetter) Get(namespace, name string) (runtime.Object, error) {
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 := appv1beta1.ApplicationList{}
err := d.c.List(context.Background(), &applications, &client.ListOptions{Namespace: namespace, LabelSelector: query.Selector()})
if err != nil {
klog.Error(err)
return nil, err
}
var result []runtime.Object
for i := range applications.Items {
result = append(result, &applications.Items[i])
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *applicationsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftApplication, ok := left.(*appv1beta1.Application)
if !ok {
return false
}
rightApplication, ok := right.(*appv1beta1.Application)
if !ok {
return false
}
switch field {
case query.FieldUpdateTime:
fallthrough
case query.FieldLastUpdateTimestamp:
return lastUpdateTime(leftApplication).After(lastUpdateTime(rightApplication))
default:
return v1alpha3.DefaultObjectMetaCompare(leftApplication.ObjectMeta, rightApplication.ObjectMeta, field)
}
}
func (d *applicationsGetter) filter(object runtime.Object, filter query.Filter) bool {
application, ok := object.(*appv1beta1.Application)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaFilter(application.ObjectMeta, filter)
}
func lastUpdateTime(application *appv1beta1.Application) time.Time {
lut := application.CreationTimestamp.Time
for _, condition := range application.Status.Conditions {
if condition.LastUpdateTime.After(lut) {
lut = condition.LastUpdateTime.Time
}
}
return lut
}

View File

@@ -1,144 +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 (
"context"
"path/filepath"
"reflect"
"testing"
core "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/klog/v2"
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"
"kubesphere.io/kubesphere/pkg/apiserver/query"
)
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)
}
}
func compare(actual *appv1beta1.Application, expects ...*appv1beta1.Application) bool {
for _, app := range expects {
if actual.Name == app.Name && actual.Namespace == app.Namespace && reflect.DeepEqual(actual.Labels, app.Labels) {
return true
}
}
return false
}
func TestGetListApplications(t *testing.T) {
e := &envtest.Environment{CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "..", "..", "config", "ks-core", "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)
}
ctx := context.Background()
ce, _ := cache.New(cfg, cache.Options{Scheme: sch})
go ce.Start(ctx)
ce.WaitForCacheSync(ctx)
c, _ = client.New(cfg, client.Options{Scheme: sch})
var labelSet1 = map[string]string{"foo-1": "bar-1"}
var labelSet2 = map[string]string{"foo-2": "bar-2"}
var ns = "ns-1"
testCases := []*appv1beta1.Application{
{
ObjectMeta: metav1.ObjectMeta{
Name: "app-1",
Namespace: ns,
Labels: labelSet1,
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "app-2",
Namespace: ns,
Labels: labelSet2,
},
},
}
// ctx := context.TODO()
createNamespace(ns, ctx)
for _, app := range testCases {
if err = c.Create(ctx, app); err != nil {
t.Fatal(err)
}
}
getter := New(ce)
results, err := getter.List(ns, &query.Query{})
if err != nil {
t.Fatal(err)
}
if results.TotalItems != len(testCases) {
t.Fatal("TotalItems is not match")
}
if len(results.Items) != len(testCases) {
t.Fatal("Items numbers is not match mock data")
}
for _, app := range results.Items {
app, err := app.(*appv1beta1.Application)
if !err {
t.Fatal(err)
}
if !compare(app, testCases...) {
t.Errorf("The results %v not match testcases %v", results.Items, testCases)
}
}
result, err := getter.Get(ns, "app-1")
if err != nil {
t.Fatal(err)
}
app := result.(*appv1beta1.Application)
if !compare(app, testCases...) {
t.Errorf("The results %v not match testcases %v", result, testCases)
}
}

View File

@@ -1,72 +1,62 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package cluster
import (
"k8s.io/apimachinery/pkg/runtime"
"context"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
clusterv1alpha1 "kubesphere.io/api/cluster/v1alpha1"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type clustersGetter struct {
informers externalversions.SharedInformerFactory
cache runtimeclient.Reader
}
func New(informers externalversions.SharedInformerFactory) v1alpha3.Interface {
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &clustersGetter{
informers: informers,
cache: cache,
}
}
func (c clustersGetter) Get(_, name string) (runtime.Object, error) {
cluster, err := c.informers.Cluster().V1alpha1().Clusters().Lister().Get(name)
if err != nil {
func (c *clustersGetter) Get(_, name string) (runtime.Object, error) {
cluster := &clusterv1alpha1.Cluster{}
if err := c.cache.Get(context.Background(), types.NamespacedName{Name: name}, cluster); err != nil {
return nil, err
}
return c.transform(cluster), nil
}
func (c clustersGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
clusters, err := c.informers.Cluster().V1alpha1().Clusters().Lister().List(query.Selector())
if err != nil {
func (c *clustersGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
cluster := &clusterv1alpha1.ClusterList{}
if err := c.cache.List(context.Background(), cluster, client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
for _, cluster := range clusters {
result = append(result, cluster)
for _, item := range cluster.Items {
result = append(result, item.DeepCopy())
}
return v1alpha3.DefaultList(result, query, c.compare, c.filter, c.transform), nil
}
func (c clustersGetter) transform(obj runtime.Object) runtime.Object {
func (c *clustersGetter) transform(obj runtime.Object) runtime.Object {
in := obj.(*clusterv1alpha1.Cluster)
out := in.DeepCopy()
out.Spec.Connection.KubeConfig = nil
return out
}
func (c clustersGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
func (c *clustersGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftCluster, ok := left.(*clusterv1alpha1.Cluster)
if !ok {
return false
@@ -80,7 +70,7 @@ func (c clustersGetter) compare(left runtime.Object, right runtime.Object, field
return v1alpha3.DefaultObjectMetaCompare(leftCluster.ObjectMeta, rightCluster.ObjectMeta, field)
}
func (c clustersGetter) filter(object runtime.Object, filter query.Filter) bool {
func (c *clustersGetter) filter(object runtime.Object, filter query.Filter) bool {
cluster, ok := object.(*clusterv1alpha1.Cluster)
if !ok {
return false

View File

@@ -1,124 +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 cluster
import (
"testing"
"github.com/google/go-cmp/cmp"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
clusterv1alpha1 "kubesphere.io/api/cluster/v1alpha1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
)
var clusters = []*clusterv1alpha1.Cluster{
{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Labels: map[string]string{
"cluster.kubesphere.io/region": "beijing",
"cluster.kubesphere.io/group": "development",
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
Labels: map[string]string{
"cluster.kubesphere.io/region": "beijing",
"cluster.kubesphere.io/group": "production",
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "whatever",
Labels: map[string]string{
"cluster.kubesphere.io/region": "shanghai",
"cluster.kubesphere.io/group": "testing",
},
},
},
}
func clustersToInterface(clusters ...*clusterv1alpha1.Cluster) []interface{} {
items := make([]interface{}, 0)
for _, cluster := range clusters {
items = append(items, cluster)
}
return items
}
func clustersToRuntimeObject(clusters ...*clusterv1alpha1.Cluster) []runtime.Object {
items := make([]runtime.Object, 0)
for _, cluster := range clusters {
items = append(items, cluster)
}
return items
}
func TestClustersGetter(t *testing.T) {
var testCases = []struct {
description string
query *query.Query
expected *api.ListResult
}{
{
description: "Test normal case",
query: &query.Query{
LabelSelector: "cluster.kubesphere.io/region=beijing",
Ascending: false,
},
expected: &api.ListResult{
TotalItems: 2,
Items: clustersToInterface(clusters[0], clusters[1]),
},
},
}
client := fake.NewSimpleClientset(clustersToRuntimeObject(clusters...)...)
informer := externalversions.NewSharedInformerFactory(client, 0)
for _, cluster := range clusters {
informer.Cluster().V1alpha1().Clusters().Informer().GetIndexer().Add(cluster)
}
for _, testCase := range testCases {
clusterGetter := New(informer)
t.Run(testCase.description, func(t *testing.T) {
result, err := clusterGetter.List("", testCase.query)
if err != nil {
t.Error(err)
}
if diff := cmp.Diff(result, testCase.expected); len(diff) != 0 {
t.Errorf("%T, got+ expected-, %s", testCase.expected, diff)
}
})
}
}

View File

@@ -1,88 +0,0 @@
/*
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.
*/
package clusterdashboard
import (
"context"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog/v2"
monitoringdashboardv1alpha2 "kubesphere.io/monitoring-dashboard/api/v1alpha2"
"sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type dashboardGetter struct {
c client.Reader
}
func New(c client.Reader) v1alpha3.Interface {
return &dashboardGetter{c}
}
func (d *dashboardGetter) Get(_, name string) (runtime.Object, error) {
dashboard := monitoringdashboardv1alpha2.ClusterDashboard{}
err := d.c.Get(context.Background(), types.NamespacedName{Name: name}, &dashboard)
if err != nil {
klog.Error(err)
return nil, err
}
return &dashboard, nil
}
func (d *dashboardGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
dashboards := monitoringdashboardv1alpha2.ClusterDashboardList{}
err := d.c.List(context.Background(), &dashboards, &client.ListOptions{LabelSelector: query.Selector()})
if err != nil {
klog.Error(err)
return nil, err
}
var result []runtime.Object
for i := range dashboards.Items {
result = append(result, &dashboards.Items[i])
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *dashboardGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftClusterDashboard, ok := left.(*monitoringdashboardv1alpha2.ClusterDashboard)
if !ok {
return false
}
rightClusterDashboard, ok := right.(*monitoringdashboardv1alpha2.ClusterDashboard)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaCompare(leftClusterDashboard.ObjectMeta, rightClusterDashboard.ObjectMeta, field)
}
func (d *dashboardGetter) filter(object runtime.Object, filter query.Filter) bool {
dashboard, ok := object.(*monitoringdashboardv1alpha2.ClusterDashboard)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaFilter(dashboard.ObjectMeta, filter)
}

View File

@@ -1,114 +0,0 @@
/*
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.
*/
package clusterdashboard
import (
"context"
"reflect"
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/scheme"
monitoringdashboardv1alpha2 "kubesphere.io/monitoring-dashboard/api/v1alpha2"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"kubesphere.io/kubesphere/pkg/apiserver/query"
)
var c client.Client
func compare(actual *monitoringdashboardv1alpha2.ClusterDashboard,
expects ...*monitoringdashboardv1alpha2.ClusterDashboard) bool {
for _, app := range expects {
if actual.Name == app.Name && reflect.DeepEqual(actual.Labels, app.Labels) {
return true
}
}
return false
}
func TestGetListClusterDashboards(t *testing.T) {
sch := scheme.Scheme
if err := monitoringdashboardv1alpha2.AddToScheme(sch); err != nil {
t.Fatalf("unable add APIs to scheme: %v", err)
}
//nolint:staticcheck
c = fake.NewFakeClientWithScheme(sch)
var labelSet1 = map[string]string{"foo-1": "bar-1"}
var labelSet2 = map[string]string{"foo-2": "bar-2"}
testCases := []*monitoringdashboardv1alpha2.ClusterDashboard{
{
ObjectMeta: metav1.ObjectMeta{
Name: "clusterdashboard-1",
Labels: labelSet1,
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "clusterdashboard-2",
Labels: labelSet2,
},
},
}
ctx := context.TODO()
for _, board := range testCases {
if err := c.Create(ctx, board); err != nil {
t.Fatal(err)
}
}
getter := New(c)
results, err := getter.List("", &query.Query{})
if err != nil {
t.Fatal(err)
}
if results.TotalItems != len(testCases) {
t.Fatal("TotalItems is not match")
}
if len(results.Items) != len(testCases) {
t.Fatal("Items numbers is not match mock data")
}
for _, dashboard := range results.Items {
dashboard, err := dashboard.(*monitoringdashboardv1alpha2.ClusterDashboard)
if !err {
t.Fatal(err)
}
if !compare(dashboard, testCases...) {
t.Errorf("The results %v not match testcases %v", results.Items, testCases)
}
}
result, err := getter.Get("", "clusterdashboard-1")
if err != nil {
t.Fatal(err)
}
dashboard := result.(*monitoringdashboardv1alpha2.ClusterDashboard)
if !compare(dashboard, testCases...) {
t.Errorf("The results %v not match testcases %v", result, testCases)
}
}

View File

@@ -1,75 +1,73 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package clusterrole
import (
"context"
"encoding/json"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
"k8s.io/klog/v2"
iamv1alpha2 "kubesphere.io/api/iam/v1alpha2"
iamv1beta1 "kubesphere.io/api/iam/v1beta1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type clusterrolesGetter struct {
sharedInformers informers.SharedInformerFactory
type clusterRolesGetter struct {
cache runtimeclient.Reader
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &clusterrolesGetter{sharedInformers: sharedInformers}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &clusterRolesGetter{cache: cache}
}
func (d *clusterrolesGetter) Get(namespace, name string) (runtime.Object, error) {
return d.sharedInformers.Rbac().V1().ClusterRoles().Lister().Get(name)
func (d *clusterRolesGetter) Get(_, name string) (runtime.Object, error) {
clusterRole := &rbacv1.ClusterRole{}
return clusterRole, d.cache.Get(context.Background(), types.NamespacedName{Name: name}, clusterRole)
}
func (d *clusterrolesGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
func (d *clusterRolesGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
var roles []*rbacv1.ClusterRole
var err error
if aggregateTo := query.Filters[iamv1alpha2.AggregateTo]; aggregateTo != "" {
if aggregateTo := query.Filters[iamv1beta1.AggregateTo]; aggregateTo != "" {
roles, err = d.fetchAggregationRoles(string(aggregateTo))
delete(query.Filters, iamv1alpha2.AggregateTo)
if err != nil {
return nil, err
}
delete(query.Filters, iamv1beta1.AggregateTo)
} else {
roles, err = d.sharedInformers.Rbac().V1().ClusterRoles().Lister().List(query.Selector())
}
if err != nil {
return nil, err
clusterRoleList := &rbacv1.ClusterRoleList{}
if err := d.cache.List(context.Background(), clusterRoleList,
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
roles = make([]*rbacv1.ClusterRole, 0)
for _, item := range clusterRoleList.Items {
roles = append(roles, item.DeepCopy())
}
}
var result []runtime.Object
for _, clusterrole := range roles {
result = append(result, clusterrole)
for _, clusterRole := range roles {
result = append(result, clusterRole)
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *clusterrolesGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
func (d *clusterRolesGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftClusterRole, ok := left.(*rbacv1.ClusterRole)
if !ok {
return false
@@ -83,7 +81,7 @@ func (d *clusterrolesGetter) compare(left runtime.Object, right runtime.Object,
return v1alpha3.DefaultObjectMetaCompare(leftClusterRole.ObjectMeta, rightClusterRole.ObjectMeta, field)
}
func (d *clusterrolesGetter) filter(object runtime.Object, filter query.Filter) bool {
func (d *clusterRolesGetter) filter(object runtime.Object, filter query.Filter) bool {
role, ok := object.(*rbacv1.ClusterRole)
if !ok {
@@ -93,7 +91,7 @@ func (d *clusterrolesGetter) filter(object runtime.Object, filter query.Filter)
return v1alpha3.DefaultObjectMetaFilter(role.ObjectMeta, filter)
}
func (d *clusterrolesGetter) fetchAggregationRoles(name string) ([]*rbacv1.ClusterRole, error) {
func (d *clusterRolesGetter) fetchAggregationRoles(name string) ([]*rbacv1.ClusterRole, error) {
roles := make([]*rbacv1.ClusterRole, 0)
obj, err := d.Get("", name)
@@ -105,7 +103,7 @@ func (d *clusterrolesGetter) fetchAggregationRoles(name string) ([]*rbacv1.Clust
return nil, err
}
if annotation := obj.(*rbacv1.ClusterRole).Annotations[iamv1alpha2.AggregationRolesAnnotation]; annotation != "" {
if annotation := obj.(*rbacv1.ClusterRole).Annotations[iamv1beta1.AggregationRolesAnnotation]; annotation != "" {
var roleNames []string
if err = json.Unmarshal([]byte(annotation), &roleNames); err == nil {

View File

@@ -1,18 +1,11 @@
//go:build exclude
/*
Copyright 2019 The KubeSphere Authors.
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
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.
*/
// TODO refactor with fake controller runtime client
package clusterrole

View File

@@ -1,61 +1,51 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package clusterrolebinding
import (
"context"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type clusterrolebindingsGetter struct {
sharedInformers informers.SharedInformerFactory
type clusterRoleBindingsGetter struct {
cache runtimeclient.Reader
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &clusterrolebindingsGetter{sharedInformers: sharedInformers}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &clusterRoleBindingsGetter{cache: cache}
}
func (d *clusterrolebindingsGetter) Get(_, name string) (runtime.Object, error) {
return d.sharedInformers.Rbac().V1().ClusterRoleBindings().Lister().Get(name)
func (d *clusterRoleBindingsGetter) Get(_, name string) (runtime.Object, error) {
clusterRoleBinding := &rbacv1.ClusterRoleBinding{}
return clusterRoleBinding, d.cache.Get(context.Background(), types.NamespacedName{Name: name}, clusterRoleBinding)
}
func (d *clusterrolebindingsGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
roleBindings, err := d.sharedInformers.Rbac().V1().ClusterRoleBindings().Lister().List(query.Selector())
if err != nil {
func (d *clusterRoleBindingsGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
clusterRoleBindings := &rbacv1.ClusterRoleBindingList{}
if err := d.cache.List(context.Background(), clusterRoleBindings,
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
for _, roleBinding := range roleBindings {
result = append(result, roleBinding)
for _, item := range clusterRoleBindings.Items {
result = append(result, item.DeepCopy())
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *clusterrolebindingsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
func (d *clusterRoleBindingsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftRoleBinding, ok := left.(*rbacv1.ClusterRoleBinding)
if !ok {
return false
@@ -69,7 +59,7 @@ func (d *clusterrolebindingsGetter) compare(left runtime.Object, right runtime.O
return v1alpha3.DefaultObjectMetaCompare(leftRoleBinding.ObjectMeta, rightRoleBinding.ObjectMeta, field)
}
func (d *clusterrolebindingsGetter) filter(object runtime.Object, filter query.Filter) bool {
func (d *clusterRoleBindingsGetter) filter(object runtime.Object, filter query.Filter) bool {
role, ok := object.(*rbacv1.ClusterRoleBinding)
if !ok {

View File

@@ -1,18 +1,11 @@
//go:build exclude
/*
Copyright 2019 The KubeSphere Authors.
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
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.
*/
// TODO refactor with fake controller runtime client
package clusterrolebinding

View File

@@ -1,25 +1,18 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package configmap
import (
"context"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
@@ -27,33 +20,32 @@ import (
)
type configmapsGetter struct {
informer informers.SharedInformerFactory
cache runtimeclient.Reader
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &configmapsGetter{informer: sharedInformers}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &configmapsGetter{cache: cache}
}
func (d *configmapsGetter) Get(namespace, name string) (runtime.Object, error) {
return d.informer.Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).Get(name)
configMap := &corev1.ConfigMap{}
return configMap, d.cache.Get(context.Background(), types.NamespacedName{Namespace: namespace, Name: name}, configMap)
}
func (d *configmapsGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
configmaps, err := d.informer.Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).List(query.Selector())
if err != nil {
configMaps := &corev1.ConfigMapList{}
if err := d.cache.List(context.Background(), configMaps, client.InNamespace(namespace),
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
for _, configmap := range configmaps {
result = append(result, configmap)
for _, item := range configMaps.Items {
result = append(result, item.DeepCopy())
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *configmapsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftCM, ok := left.(*corev1.ConfigMap)
if !ok {
return false

View File

@@ -1,18 +1,11 @@
//go:build exclude
/*
Copyright 2019 The KubeSphere Authors.
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
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.
*/
// TODO refactor with fake controller runtime client
package configmap

View File

@@ -0,0 +1,112 @@
/*
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package cronjob
import (
"context"
"strings"
"github.com/Masterminds/semver/v3"
batchv1 "k8s.io/api/batch/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
"kubesphere.io/kubesphere/pkg/scheme"
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
)
type cronJobsGetter struct {
cache runtimeclient.Reader
gvk schema.GroupVersionKind
listGVK schema.GroupVersionKind
}
func New(cache runtimeclient.Reader, k8sVersion *semver.Version) v1alpha3.Interface {
gvk := batchv1.SchemeGroupVersion.WithKind("CronJob")
listGVK := schema.GroupVersionKind{
Group: gvk.Group,
Version: gvk.Version,
Kind: gvk.Kind + "List",
}
if k8sutil.ServeBatchV1beta1(k8sVersion) {
gvk.Version = "v1beta1"
listGVK.Version = "v1beta1"
}
return &cronJobsGetter{
cache: cache,
gvk: gvk,
listGVK: listGVK,
}
}
func (d *cronJobsGetter) Get(namespace, name string) (runtime.Object, error) {
obj, err := scheme.Scheme.New(d.gvk)
if err != nil {
return nil, err
}
cronJob := obj.(client.Object)
return cronJob, d.cache.Get(context.Background(), types.NamespacedName{Namespace: namespace, Name: name}, cronJob)
}
func (d *cronJobsGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
listObj := &unstructured.UnstructuredList{}
listObj.SetGroupVersionKind(d.listGVK)
if err := d.cache.List(context.Background(), listObj, client.InNamespace(namespace),
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
if err := listObj.EachListItem(func(object runtime.Object) error {
result = append(result, object)
return nil
}); err != nil {
return nil, err
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func cronJobStatus(item *unstructured.Unstructured) string {
suspend, _, _ := unstructured.NestedBool(item.UnstructuredContent(), "spec", "suspend")
if suspend {
return "paused"
}
return "running"
}
func (d *cronJobsGetter) filter(object runtime.Object, filter query.Filter) bool {
job, ok := object.(*unstructured.Unstructured)
if !ok {
return false
}
switch filter.Field {
case query.FieldStatus:
return strings.Compare(cronJobStatus(job), string(filter.Value)) == 0
default:
return v1alpha3.DefaultObjectMetaFilter(k8sutil.GetObjectMeta(job), filter)
}
}
func (d *cronJobsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftJob, ok := left.(*unstructured.Unstructured)
if !ok {
return false
}
rightJob, ok := right.(*unstructured.Unstructured)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaCompare(k8sutil.GetObjectMeta(leftJob), k8sutil.GetObjectMeta(rightJob), field)
}

View File

@@ -1,26 +1,19 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package customresourcedefinition
import (
"context"
"strings"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apiextensionsinformers "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions"
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/kubesphere/pkg/api"
@@ -29,30 +22,28 @@ import (
)
type crdGetter struct {
informers apiextensionsinformers.SharedInformerFactory
cache runtimeclient.Reader
}
func New(informers apiextensionsinformers.SharedInformerFactory) v1alpha3.Interface {
return &crdGetter{
informers: informers,
}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &crdGetter{cache: cache}
}
func (c crdGetter) Get(_, name string) (runtime.Object, error) {
return c.informers.Apiextensions().V1().CustomResourceDefinitions().Lister().Get(name)
crd := &v1.CustomResourceDefinition{}
return crd, c.cache.Get(context.Background(), types.NamespacedName{Name: name}, crd)
}
func (c crdGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
crds, err := c.informers.Apiextensions().V1().CustomResourceDefinitions().Lister().List(query.Selector())
if err != nil {
crds := &v1.CustomResourceDefinitionList{}
if err := c.cache.List(context.Background(), crds,
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
for _, crd := range crds {
result = append(result, crd)
for _, item := range crds.Items {
result = append(result, item.DeepCopy())
}
return v1alpha3.DefaultList(result, query, c.compare, c.filter), nil
}

View File

@@ -1,115 +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 customresourcedefinition
import (
"testing"
"github.com/google/go-cmp/cmp"
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
fakeapiextensions "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake"
apiextensionsinformers "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
)
var crds = []*v1.CustomResourceDefinition{
{
ObjectMeta: metav1.ObjectMeta{
Name: "clusters.cluster.kubesphere.io",
Labels: map[string]string{
"controller-tools.k8s.io": "1.0",
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "workspaces.tenant.kubesphere.io",
Labels: map[string]string{
"controller-tools.k8s.io": "1.0",
},
},
},
}
func crdsToRuntimeObjects(crds ...*v1.CustomResourceDefinition) []runtime.Object {
items := make([]runtime.Object, 0)
for _, crd := range crds {
items = append(items, crd)
}
return items
}
func crdsToInterface(crds ...*v1.CustomResourceDefinition) []interface{} {
items := make([]interface{}, 0)
for _, crd := range crds {
items = append(items, crd)
}
return items
}
func TestCrdGetterList(t *testing.T) {
var testCases = []struct {
description string
query *query.Query
expected *api.ListResult
}{
{
description: "Test normal case",
query: &query.Query{
Filters: map[query.Field]query.Value{
query.FieldName: "clusters.cluster.kubesphere.io",
},
},
expected: &api.ListResult{
TotalItems: 1,
Items: crdsToInterface(crds[0]),
},
},
}
client := fakeapiextensions.NewSimpleClientset(crdsToRuntimeObjects(crds...)...)
informers := apiextensionsinformers.NewSharedInformerFactory(client, 0)
for _, crd := range crds {
informers.Apiextensions().V1().CustomResourceDefinitions().Informer().GetIndexer().Add(crd)
}
for _, testCase := range testCases {
crdGetter := New(informers)
t.Run(testCase.description, func(t *testing.T) {
result, err := crdGetter.List("", testCase.query)
if err != nil {
t.Error(err)
}
if diff := cmp.Diff(result, testCase.expected); len(diff) != 0 {
t.Errorf("%T, got+ expected-, %s", testCase.expected, diff)
}
})
}
}

View File

@@ -1,27 +1,20 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package daemonset
import (
"context"
"strings"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
appsv1 "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
@@ -35,34 +28,32 @@ const (
)
type daemonSetGetter struct {
sharedInformers informers.SharedInformerFactory
cache runtimeclient.Reader
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &daemonSetGetter{sharedInformers: sharedInformers}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &daemonSetGetter{cache: cache}
}
func (d *daemonSetGetter) Get(namespace, name string) (runtime.Object, error) {
return d.sharedInformers.Apps().V1().DaemonSets().Lister().DaemonSets(namespace).Get(name)
daemonSet := &appsv1.DaemonSet{}
return daemonSet, d.cache.Get(context.Background(), types.NamespacedName{Namespace: namespace, Name: name}, daemonSet)
}
func (d *daemonSetGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
// first retrieves all daemonSets within given namespace
daemonSets, err := d.sharedInformers.Apps().V1().DaemonSets().Lister().DaemonSets(namespace).List(query.Selector())
if err != nil {
daemonSets := &appsv1.DaemonSetList{}
if err := d.cache.List(context.Background(), daemonSets, client.InNamespace(namespace),
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
for _, daemonSet := range daemonSets {
result = append(result, daemonSet)
for _, item := range daemonSets.Items {
result = append(result, item.DeepCopy())
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *daemonSetGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftDaemonSet, ok := left.(*appsv1.DaemonSet)
if !ok {
return false
@@ -83,13 +74,13 @@ func (d *daemonSetGetter) filter(object runtime.Object, filter query.Filter) boo
}
switch filter.Field {
case query.FieldStatus:
return strings.Compare(daemonsetStatus(&daemonSet.Status), string(filter.Value)) == 0
return strings.Compare(daemonSetStatus(&daemonSet.Status), string(filter.Value)) == 0
default:
return v1alpha3.DefaultObjectMetaFilter(daemonSet.ObjectMeta, filter)
}
}
func daemonsetStatus(status *appsv1.DaemonSetStatus) string {
func daemonSetStatus(status *appsv1.DaemonSetStatus) string {
if status.DesiredNumberScheduled == 0 && status.NumberReady == 0 {
return statusStopped
} else if status.DesiredNumberScheduled == status.NumberReady {

View File

@@ -1,18 +1,11 @@
//go:build exclude
/*
Copyright 2019 The KubeSphere Authors.
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
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.
*/
// TODO refactor with fake controller runtime client
package daemonset

View File

@@ -1,88 +0,0 @@
/*
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.
*/
package dashboard
import (
"context"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog/v2"
monitoringdashboardv1alpha2 "kubesphere.io/monitoring-dashboard/api/v1alpha2"
"sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type dashboardGetter struct {
c client.Reader
}
func New(c client.Reader) v1alpha3.Interface {
return &dashboardGetter{c}
}
func (d *dashboardGetter) Get(namespace, name string) (runtime.Object, error) {
dashboard := monitoringdashboardv1alpha2.Dashboard{}
err := d.c.Get(context.Background(), types.NamespacedName{Namespace: namespace, Name: name}, &dashboard)
if err != nil {
klog.Error(err)
return nil, err
}
return &dashboard, nil
}
func (d *dashboardGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
dashboards := monitoringdashboardv1alpha2.DashboardList{}
err := d.c.List(context.Background(), &dashboards, &client.ListOptions{Namespace: namespace, LabelSelector: query.Selector()})
if err != nil {
klog.Error(err)
return nil, err
}
var result []runtime.Object
for i := range dashboards.Items {
result = append(result, &dashboards.Items[i])
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *dashboardGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftDashboard, ok := left.(*monitoringdashboardv1alpha2.Dashboard)
if !ok {
return false
}
rightDashboard, ok := right.(*monitoringdashboardv1alpha2.Dashboard)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaCompare(leftDashboard.ObjectMeta, rightDashboard.ObjectMeta, field)
}
func (d *dashboardGetter) filter(object runtime.Object, filter query.Filter) bool {
dashboard, ok := object.(*monitoringdashboardv1alpha2.Dashboard)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaFilter(dashboard.ObjectMeta, filter)
}

View File

@@ -1,116 +0,0 @@
/*
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.
*/
package dashboard
import (
"context"
"reflect"
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/scheme"
monitoringdashboardv1alpha2 "kubesphere.io/monitoring-dashboard/api/v1alpha2"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"kubesphere.io/kubesphere/pkg/apiserver/query"
)
var c client.Client
func compare(actual *monitoringdashboardv1alpha2.Dashboard, expects ...*monitoringdashboardv1alpha2.Dashboard) bool {
for _, app := range expects {
if actual.Name == app.Name && actual.Namespace == app.Namespace && reflect.DeepEqual(actual.Labels, app.Labels) {
return true
}
}
return false
}
func TestGetListDashboards(t *testing.T) {
sch := scheme.Scheme
if err := monitoringdashboardv1alpha2.AddToScheme(sch); err != nil {
t.Fatalf("unable add APIs to scheme: %v", err)
}
//nolint:staticcheck
c = fake.NewFakeClientWithScheme(sch)
var labelSet1 = map[string]string{"foo-1": "bar-1"}
var labelSet2 = map[string]string{"foo-2": "bar-2"}
var ns = "ns-1"
testCases := []*monitoringdashboardv1alpha2.Dashboard{
{
ObjectMeta: metav1.ObjectMeta{
Name: "dashboard-1",
Namespace: ns,
Labels: labelSet1,
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "dashboard-2",
Namespace: ns,
Labels: labelSet2,
},
},
}
ctx := context.TODO()
for _, board := range testCases {
if err := c.Create(ctx, board); err != nil {
t.Fatal(err)
}
}
getter := New(c)
results, err := getter.List(ns, &query.Query{})
if err != nil {
t.Fatal(err)
}
if results.TotalItems != len(testCases) {
t.Fatal("TotalItems is not match")
}
if len(results.Items) != len(testCases) {
t.Fatal("Items numbers is not match mock data")
}
for _, dashboard := range results.Items {
dashboard, err := dashboard.(*monitoringdashboardv1alpha2.Dashboard)
if !err {
t.Fatal(err)
}
if !compare(dashboard, testCases...) {
t.Errorf("The results %v not match testcases %v", results.Items, testCases)
}
}
result, err := getter.Get(ns, "dashboard-1")
if err != nil {
t.Fatal(err)
}
dashboard := result.(*monitoringdashboardv1alpha2.Dashboard)
if !compare(dashboard, testCases...) {
t.Errorf("The results %v not match testcases %v", result, testCases)
}
}

View File

@@ -1,33 +1,26 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package deployment
import (
"context"
"strings"
"time"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"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"
v1 "k8s.io/api/apps/v1"
appsv1 "k8s.io/api/apps/v1"
)
const (
@@ -37,40 +30,38 @@ const (
)
type deploymentsGetter struct {
sharedInformers informers.SharedInformerFactory
cache runtimeclient.Reader
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &deploymentsGetter{sharedInformers: sharedInformers}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &deploymentsGetter{cache: cache}
}
func (d *deploymentsGetter) Get(namespace, name string) (runtime.Object, error) {
return d.sharedInformers.Apps().V1().Deployments().Lister().Deployments(namespace).Get(name)
deployment := &appsv1.Deployment{}
return deployment, d.cache.Get(context.Background(), types.NamespacedName{Namespace: namespace, Name: name}, deployment)
}
func (d *deploymentsGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
// first retrieves all deployments within given namespace
deployments, err := d.sharedInformers.Apps().V1().Deployments().Lister().Deployments(namespace).List(query.Selector())
if err != nil {
deployments := &appsv1.DeploymentList{}
if err := d.cache.List(context.Background(), deployments, client.InNamespace(namespace),
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
for _, deployment := range deployments {
result = append(result, deployment)
for _, item := range deployments.Items {
result = append(result, item.DeepCopy())
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *deploymentsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftDeployment, ok := left.(*v1.Deployment)
leftDeployment, ok := left.(*appsv1.Deployment)
if !ok {
return false
}
rightDeployment, ok := right.(*v1.Deployment)
rightDeployment, ok := right.(*appsv1.Deployment)
if !ok {
return false
}
@@ -86,7 +77,7 @@ func (d *deploymentsGetter) compare(left runtime.Object, right runtime.Object, f
}
func (d *deploymentsGetter) filter(object runtime.Object, filter query.Filter) bool {
deployment, ok := object.(*v1.Deployment)
deployment, ok := object.(*appsv1.Deployment)
if !ok {
return false
}
@@ -99,7 +90,7 @@ func (d *deploymentsGetter) filter(object runtime.Object, filter query.Filter) b
}
}
func deploymentStatus(status v1.DeploymentStatus) string {
func deploymentStatus(status appsv1.DeploymentStatus) string {
if status.ReadyReplicas == 0 && status.Replicas == 0 {
return statusStopped
} else if status.ReadyReplicas == status.Replicas {
@@ -109,7 +100,7 @@ func deploymentStatus(status v1.DeploymentStatus) string {
}
}
func lastUpdateTime(deployment *v1.Deployment) time.Time {
func lastUpdateTime(deployment *appsv1.Deployment) time.Time {
lut := deployment.CreationTimestamp.Time
for _, condition := range deployment.Status.Conditions {
if condition.LastUpdateTime.After(lut) {

View File

@@ -1,18 +1,11 @@
//go:build exclude
/*
Copyright 2019 The KubeSphere Authors.
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
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.
*/
// TODO refactor with fake controller runtime client
package deployment

View File

@@ -1,75 +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 devops
import (
"k8s.io/apimachinery/pkg/runtime"
devopsv1alpha3 "kubesphere.io/api/devops/v1alpha3"
"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"
)
type devopsGetter struct {
informers ksinformers.SharedInformerFactory
}
func New(ksinformer ksinformers.SharedInformerFactory) v1alpha3.Interface {
return &devopsGetter{informers: ksinformer}
}
func (n devopsGetter) Get(_, name string) (runtime.Object, error) {
return n.informers.Devops().V1alpha3().DevOpsProjects().Lister().Get(name)
}
func (n devopsGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
projects, err := n.informers.Devops().V1alpha3().DevOpsProjects().Lister().List(query.Selector())
if err != nil {
return nil, err
}
var result []runtime.Object
for _, project := range projects {
result = append(result, project)
}
return v1alpha3.DefaultList(result, query, n.compare, n.filter), nil
}
func (n devopsGetter) filter(item runtime.Object, filter query.Filter) bool {
devOpsProject, ok := item.(*devopsv1alpha3.DevOpsProject)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaFilter(devOpsProject.ObjectMeta, filter)
}
func (n devopsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftProject, ok := left.(*devopsv1alpha3.DevOpsProject)
if !ok {
return false
}
rightProject, ok := right.(*devopsv1alpha3.DevOpsProject)
if !ok {
return true
}
return v1alpha3.DefaultObjectMetaCompare(leftProject.ObjectMeta, rightProject.ObjectMeta, field)
}

View File

@@ -1,17 +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 devops

View File

@@ -1,94 +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 federatedapplication
import (
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/api/types/v1beta1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type fedApplicationsGetter struct {
informer informers.SharedInformerFactory
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &fedApplicationsGetter{informer: sharedInformers}
}
func (d *fedApplicationsGetter) Get(namespace, name string) (runtime.Object, error) {
return d.informer.Types().V1beta1().FederatedApplications().Lister().FederatedApplications(namespace).Get(name)
}
func (d *fedApplicationsGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
applications, err := d.informer.Types().V1beta1().FederatedApplications().Lister().FederatedApplications(namespace).List(query.Selector())
if err != nil {
return nil, err
}
var result []runtime.Object
for _, app := range applications {
result = append(result, app)
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *fedApplicationsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftApplication, ok := left.(*v1beta1.FederatedApplication)
if !ok {
return false
}
rightApplication, ok := right.(*v1beta1.FederatedApplication)
if !ok {
return false
}
switch field {
case query.FieldUpdateTime:
fallthrough
case query.FieldLastUpdateTimestamp:
return lastUpdateTime(leftApplication) > (lastUpdateTime(rightApplication))
default:
return v1alpha3.DefaultObjectMetaCompare(leftApplication.ObjectMeta, rightApplication.ObjectMeta, field)
}
}
func (d *fedApplicationsGetter) filter(object runtime.Object, filter query.Filter) bool {
application, ok := object.(*v1beta1.FederatedApplication)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaFilter(application.ObjectMeta, filter)
}
func lastUpdateTime(application *v1beta1.FederatedApplication) string {
lut := application.CreationTimestamp.Time.String()
for _, condition := range application.Status.Conditions {
if condition.LastUpdateTime > lut {
lut = condition.LastUpdateTime
}
}
return lut
}

View File

@@ -1,78 +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 federatedconfigmap
import (
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/api/types/v1beta1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type fedConfigMapsGetter struct {
informer informers.SharedInformerFactory
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &fedConfigMapsGetter{informer: sharedInformers}
}
func (d *fedConfigMapsGetter) Get(namespace, name string) (runtime.Object, error) {
return d.informer.Types().V1beta1().FederatedConfigMaps().Lister().FederatedConfigMaps(namespace).Get(name)
}
func (d *fedConfigMapsGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
configmaps, err := d.informer.Types().V1beta1().FederatedConfigMaps().Lister().FederatedConfigMaps(namespace).List(query.Selector())
if err != nil {
return nil, err
}
var result []runtime.Object
for _, configmap := range configmaps {
result = append(result, configmap)
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *fedConfigMapsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftCM, ok := left.(*v1beta1.FederatedConfigMap)
if !ok {
return false
}
rightCM, ok := right.(*v1beta1.FederatedConfigMap)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaCompare(leftCM.ObjectMeta, rightCM.ObjectMeta, field)
}
func (d *fedConfigMapsGetter) filter(object runtime.Object, filter query.Filter) bool {
configMap, ok := object.(*v1beta1.FederatedConfigMap)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaFilter(configMap.ObjectMeta, filter)
}

View File

@@ -1,98 +0,0 @@
/*
Copyright 2020 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 federateddeployment
import (
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/api/types/v1beta1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type fedreatedDeploymentGetter struct {
informer informers.SharedInformerFactory
}
func New(informer informers.SharedInformerFactory) v1alpha3.Interface {
return &fedreatedDeploymentGetter{
informer: informer,
}
}
func (f *fedreatedDeploymentGetter) Get(namespace, name string) (runtime.Object, error) {
return f.informer.Types().V1beta1().FederatedDeployments().Lister().FederatedDeployments(namespace).Get(name)
}
func (f *fedreatedDeploymentGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
federatedDeployments, err := f.informer.Types().V1beta1().FederatedDeployments().Lister().FederatedDeployments(namespace).List(query.Selector())
if err != nil {
return nil, err
}
var result []runtime.Object
for _, fedDeployment := range federatedDeployments {
result = append(result, fedDeployment)
}
return v1alpha3.DefaultList(result, query, f.compare, f.filter), nil
}
func (f *fedreatedDeploymentGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftFedDeployment, ok := left.(*v1beta1.FederatedDeployment)
if !ok {
return false
}
rightFedDeployment, ok := right.(*v1beta1.FederatedDeployment)
if !ok {
return false
}
switch field {
case query.FieldUpdateTime:
fallthrough
case query.FieldLastUpdateTimestamp:
return lastUpdateTime(leftFedDeployment) > lastUpdateTime(rightFedDeployment)
default:
return v1alpha3.DefaultObjectMetaCompare(leftFedDeployment.ObjectMeta, rightFedDeployment.ObjectMeta, field)
}
}
func (f *fedreatedDeploymentGetter) filter(object runtime.Object, filter query.Filter) bool {
fedDeployment, ok := object.(*v1beta1.FederatedDeployment)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaFilter(fedDeployment.ObjectMeta, filter)
}
func lastUpdateTime(fedDeployment *v1beta1.FederatedDeployment) string {
lut := fedDeployment.CreationTimestamp.Time.String()
for _, condition := range fedDeployment.Status.Conditions {
if condition.LastUpdateTime > lut {
lut = condition.LastUpdateTime
}
}
return lut
}

View File

@@ -1,77 +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 federatedingress
import (
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/api/types/v1beta1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type fedIngressGetter struct {
sharedInformers informers.SharedInformerFactory
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &fedIngressGetter{sharedInformers: sharedInformers}
}
func (g *fedIngressGetter) Get(namespace, name string) (runtime.Object, error) {
return g.sharedInformers.Types().V1beta1().FederatedIngresses().Lister().FederatedIngresses(namespace).Get(name)
}
func (g *fedIngressGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
// first retrieves all deployments within given namespace
ingresses, err := g.sharedInformers.Types().V1beta1().FederatedIngresses().Lister().FederatedIngresses(namespace).List(query.Selector())
if err != nil {
return nil, err
}
var result []runtime.Object
for _, ingress := range ingresses {
result = append(result, ingress)
}
return v1alpha3.DefaultList(result, query, g.compare, g.filter), nil
}
func (g *fedIngressGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftIngress, ok := left.(*v1beta1.FederatedIngress)
if !ok {
return false
}
rightIngress, ok := right.(*v1beta1.FederatedIngress)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaCompare(leftIngress.ObjectMeta, rightIngress.ObjectMeta, field)
}
func (g *fedIngressGetter) filter(object runtime.Object, filter query.Filter) bool {
deployment, ok := object.(*v1beta1.FederatedIngress)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaFilter(deployment.ObjectMeta, filter)
}

View File

@@ -1,75 +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 federatednamespace
import (
"k8s.io/apimachinery/pkg/runtime"
typesv1beta1 "kubesphere.io/api/types/v1beta1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type federatedNamespacesGetter struct {
informers informers.SharedInformerFactory
}
func New(informers informers.SharedInformerFactory) v1alpha3.Interface {
return &federatedNamespacesGetter{informers: informers}
}
func (n federatedNamespacesGetter) Get(namespace, name string) (runtime.Object, error) {
return n.informers.Types().V1beta1().FederatedNamespaces().Lister().FederatedNamespaces(namespace).Get(name)
}
func (n federatedNamespacesGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
ns, err := n.informers.Types().V1beta1().FederatedNamespaces().Lister().List(query.Selector())
if err != nil {
return nil, err
}
var result []runtime.Object
for _, item := range ns {
result = append(result, item)
}
return v1alpha3.DefaultList(result, query, n.compare, n.filter), nil
}
func (n federatedNamespacesGetter) filter(item runtime.Object, filter query.Filter) bool {
namespace, ok := item.(*typesv1beta1.FederatedNamespace)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaFilter(namespace.ObjectMeta, filter)
}
func (n federatedNamespacesGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftNs, ok := left.(*typesv1beta1.FederatedNamespace)
if !ok {
return false
}
rightNs, ok := right.(*typesv1beta1.FederatedNamespace)
if !ok {
return true
}
return v1alpha3.DefaultObjectMetaCompare(leftNs.ObjectMeta, rightNs.ObjectMeta, field)
}

View File

@@ -1,17 +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 federatednamespace

View File

@@ -1,84 +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 federatedpersistentvolumeclaim
import (
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/api/types/v1beta1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
const (
storageClassName = "storageClassName"
)
type fedPersistentVolumeClaimGetter struct {
informers informers.SharedInformerFactory
}
func New(informer informers.SharedInformerFactory) v1alpha3.Interface {
return &fedPersistentVolumeClaimGetter{informers: informer}
}
func (p *fedPersistentVolumeClaimGetter) Get(namespace, name string) (runtime.Object, error) {
return p.informers.Types().V1beta1().FederatedPersistentVolumeClaims().Lister().FederatedPersistentVolumeClaims(namespace).Get(name)
}
func (p *fedPersistentVolumeClaimGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
all, err := p.informers.Types().V1beta1().FederatedPersistentVolumeClaims().Lister().FederatedPersistentVolumeClaims(namespace).List(query.Selector())
if err != nil {
return nil, err
}
var result []runtime.Object
for _, pvc := range all {
result = append(result, pvc)
}
return v1alpha3.DefaultList(result, query, p.compare, p.filter), nil
}
func (p *fedPersistentVolumeClaimGetter) compare(left, right runtime.Object, field query.Field) bool {
leftSnapshot, ok := left.(*v1beta1.FederatedPersistentVolumeClaim)
if !ok {
return false
}
rightSnapshot, ok := right.(*v1beta1.FederatedPersistentVolumeClaim)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaCompare(leftSnapshot.ObjectMeta, rightSnapshot.ObjectMeta, field)
}
func (p *fedPersistentVolumeClaimGetter) filter(object runtime.Object, filter query.Filter) bool {
pvc, ok := object.(*v1beta1.FederatedPersistentVolumeClaim)
if !ok {
return false
}
switch filter.Field {
case storageClassName:
return pvc.Spec.Template.Spec.StorageClassName != nil && *pvc.Spec.Template.Spec.StorageClassName == string(filter.Value)
default:
return v1alpha3.DefaultObjectMetaFilter(pvc.ObjectMeta, filter)
}
}

View File

@@ -1,217 +0,0 @@
package federatedpersistentvolumeclaim
import (
"testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"github.com/google/go-cmp/cmp"
fedv1beta1 "kubesphere.io/api/types/v1beta1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
var (
testStorageClassName = "sc1"
)
var (
pvc1 = &fedv1beta1.FederatedPersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "pvc-1",
Namespace: "default",
},
}
pvc2 = &fedv1beta1.FederatedPersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "pvc-2",
Namespace: "default",
},
Spec: fedv1beta1.FederatedPersistentVolumeClaimSpec{
Template: fedv1beta1.PersistentVolumeClaimTemplate{
Spec: corev1.PersistentVolumeClaimSpec{
StorageClassName: &testStorageClassName,
},
},
},
}
pvc3 = &fedv1beta1.FederatedPersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "pvc-3",
Namespace: "default",
Labels: map[string]string{
"kubesphere.io/in-use": "false",
},
},
Spec: fedv1beta1.FederatedPersistentVolumeClaimSpec{
Template: fedv1beta1.PersistentVolumeClaimTemplate{
Spec: corev1.PersistentVolumeClaimSpec{
StorageClassName: &testStorageClassName,
},
},
},
}
federatedPersistentVolumeClaims = []*fedv1beta1.FederatedPersistentVolumeClaim{pvc1, pvc2, pvc3}
)
func fedPVCsToInterface(federatedPersistentVolumeClaims ...*fedv1beta1.FederatedPersistentVolumeClaim) []interface{} {
items := make([]interface{}, 0)
for _, fedPVC := range federatedPersistentVolumeClaims {
items = append(items, fedPVC)
}
return items
}
func fedPVCsToRuntimeObject(federatedPersistentVolumeClaims ...*fedv1beta1.FederatedPersistentVolumeClaim) []runtime.Object {
items := make([]runtime.Object, 0)
for _, fedPVC := range federatedPersistentVolumeClaims {
items = append(items, fedPVC)
}
return items
}
func prepare() (v1alpha3.Interface, error) {
client := fake.NewSimpleClientset(fedPVCsToRuntimeObject(federatedPersistentVolumeClaims...)...)
informer := externalversions.NewSharedInformerFactory(client, 0)
for _, fedPVC := range federatedPersistentVolumeClaims {
err := informer.Types().V1beta1().FederatedPersistentVolumeClaims().Informer().GetIndexer().Add(fedPVC)
if err != nil {
return nil, err
}
}
return New(informer), nil
}
func TestGet(t *testing.T) {
tests := []struct {
namespace string
name string
expected runtime.Object
expectedErr error
}{
{
namespace: "default",
name: "pvc-1",
expected: fedPVCsToRuntimeObject(pvc1)[0],
expectedErr: nil,
},
}
getter, err := prepare()
if err != nil {
t.Fatal(err)
}
for _, test := range tests {
pvc, err := getter.Get(test.namespace, test.name)
if test.expectedErr != nil && err != test.expectedErr {
t.Errorf("expected error, got nothing")
} else if err != nil {
t.Fatal(err)
}
diff := cmp.Diff(pvc, test.expected)
if diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
}
}
}
func TestList(t *testing.T) {
tests := []struct {
description string
namespace string
query *query.Query
expected *api.ListResult
expectedErr error
}{
{
description: "test name filter",
namespace: "default",
query: &query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{query.FieldName: query.Value(pvc1.Name)},
},
expected: &api.ListResult{
Items: fedPVCsToInterface(federatedPersistentVolumeClaims[0]),
TotalItems: 1,
},
expectedErr: nil,
},
{
description: "test storageClass filter",
namespace: "default",
query: &query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{query.Field(storageClassName): query.Value(*pvc2.Spec.Template.Spec.StorageClassName)},
},
expected: &api.ListResult{
Items: fedPVCsToInterface(federatedPersistentVolumeClaims[2], federatedPersistentVolumeClaims[1]),
TotalItems: 2,
},
expectedErr: nil,
},
{
description: "test label filter",
namespace: "default",
query: &query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
LabelSelector: "kubesphere.io/in-use=false",
Filters: map[query.Field]query.Value{query.Field(storageClassName): query.Value(*pvc2.Spec.Template.Spec.StorageClassName)},
},
expected: &api.ListResult{
Items: fedPVCsToInterface(federatedPersistentVolumeClaims[2]),
TotalItems: 1,
},
expectedErr: nil,
},
}
lister, err := prepare()
if err != nil {
t.Fatal(err)
}
for _, test := range tests {
got, err := lister.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, test.expected); diff != "" {
t.Errorf("[%s] %T differ (-got, +want): %s", test.description, test.expected, diff)
}
}
}

View File

@@ -1,85 +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 federatedsecret
import (
"strings"
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/api/types/v1beta1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type fedSecretGetter struct {
sharedInformers informers.SharedInformerFactory
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &fedSecretGetter{sharedInformers: sharedInformers}
}
func (d *fedSecretGetter) Get(namespace, name string) (runtime.Object, error) {
return d.sharedInformers.Types().V1beta1().FederatedSecrets().Lister().FederatedSecrets(namespace).Get(name)
}
func (d *fedSecretGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
secrets, err := d.sharedInformers.Types().V1beta1().FederatedSecrets().Lister().FederatedSecrets(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, d.compare, d.filter), nil
}
func (d *fedSecretGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftSecret, ok := left.(*v1beta1.FederatedSecret)
if !ok {
return false
}
rightSecret, ok := right.(*v1beta1.FederatedSecret)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaCompare(leftSecret.ObjectMeta, rightSecret.ObjectMeta, field)
}
func (d *fedSecretGetter) filter(object runtime.Object, filter query.Filter) bool {
fedSecret, ok := object.(*v1beta1.FederatedSecret)
if !ok {
return false
}
switch filter.Field {
case query.FieldType:
return strings.Compare(string(fedSecret.Spec.Template.Type), string(filter.Value)) == 0
default:
return v1alpha3.DefaultObjectMetaFilter(fedSecret.ObjectMeta, filter)
}
}

View File

@@ -1,79 +0,0 @@
/*
Copyright 2020 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 federatedservice
import (
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/api/types/v1beta1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type federatedServiceGetter struct {
informer informers.SharedInformerFactory
}
func New(informer informers.SharedInformerFactory) v1alpha3.Interface {
return &federatedServiceGetter{
informer: informer,
}
}
func (f *federatedServiceGetter) Get(namespace, name string) (runtime.Object, error) {
return f.informer.Types().V1beta1().FederatedServices().Lister().FederatedServices(namespace).Get(name)
}
func (f *federatedServiceGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
federatedServices, err := f.informer.Types().V1beta1().FederatedServices().Lister().FederatedServices(namespace).List(query.Selector())
if err != nil {
return nil, err
}
var result []runtime.Object
for _, fedService := range federatedServices {
result = append(result, fedService)
}
return v1alpha3.DefaultList(result, query, f.compare, f.filter), nil
}
func (f *federatedServiceGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftService, ok := left.(*v1beta1.FederatedService)
if !ok {
return false
}
rightService, ok := right.(*v1beta1.FederatedService)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaCompare(leftService.ObjectMeta, rightService.ObjectMeta, field)
}
func (f *federatedServiceGetter) filter(object runtime.Object, filter query.Filter) bool {
service, ok := object.(*v1beta1.FederatedService)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaFilter(service.ObjectMeta, filter)
}

View File

@@ -1,79 +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 federatedstatefulset
import (
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/api/types/v1beta1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type fedStatefulSetGetter struct {
sharedInformers informers.SharedInformerFactory
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &fedStatefulSetGetter{sharedInformers: sharedInformers}
}
func (d *fedStatefulSetGetter) Get(namespace, name string) (runtime.Object, error) {
return d.sharedInformers.Types().V1beta1().FederatedStatefulSets().Lister().FederatedStatefulSets(namespace).Get(name)
}
func (d *fedStatefulSetGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
// first retrieves all statefulSets within given namespace
statefulSets, err := d.sharedInformers.Types().V1beta1().FederatedStatefulSets().Lister().FederatedStatefulSets(namespace).List(query.Selector())
if err != nil {
return nil, err
}
var result []runtime.Object
for _, statefulSet := range statefulSets {
result = append(result, statefulSet)
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *fedStatefulSetGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftStatefulSet, ok := left.(*v1beta1.FederatedStatefulSet)
if !ok {
return false
}
rightStatefulSet, ok := right.(*v1beta1.FederatedStatefulSet)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaCompare(leftStatefulSet.ObjectMeta, rightStatefulSet.ObjectMeta, field)
}
func (d *fedStatefulSetGetter) filter(object runtime.Object, filter query.Filter) bool {
statefulSet, ok := object.(*v1beta1.FederatedStatefulSet)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaFilter(statefulSet.ObjectMeta, filter)
}

View File

@@ -1,62 +1,61 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package globalrole
import (
"context"
"encoding/json"
"sigs.k8s.io/controller-runtime/pkg/client"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog/v2"
iamv1alpha2 "kubesphere.io/api/iam/v1alpha2"
iamv1beta1 "kubesphere.io/api/iam/v1beta1"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type globalrolesGetter struct {
sharedInformers informers.SharedInformerFactory
type globalRolesGetter struct {
cache runtimeclient.Reader
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &globalrolesGetter{sharedInformers: sharedInformers}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &globalRolesGetter{cache: cache}
}
func (d *globalrolesGetter) Get(_, name string) (runtime.Object, error) {
return d.sharedInformers.Iam().V1alpha2().GlobalRoles().Lister().Get(name)
func (d *globalRolesGetter) Get(_, name string) (runtime.Object, error) {
globalRole := &iamv1beta1.GlobalRole{}
return globalRole, d.cache.Get(context.Background(), types.NamespacedName{Name: name}, globalRole)
}
func (d *globalrolesGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
var roles []*iamv1alpha2.GlobalRole
func (d *globalRolesGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
var roles []*iamv1beta1.GlobalRole
var err error
if aggregateTo := query.Filters[iamv1alpha2.AggregateTo]; aggregateTo != "" {
if aggregateTo := query.Filters[iamv1beta1.AggregateTo]; aggregateTo != "" {
roles, err = d.fetchAggregationRoles(string(aggregateTo))
delete(query.Filters, iamv1alpha2.AggregateTo)
if err != nil {
return nil, err
}
delete(query.Filters, iamv1beta1.AggregateTo)
} else {
roles, err = d.sharedInformers.Iam().V1alpha2().GlobalRoles().Lister().List(query.Selector())
}
if err != nil {
return nil, err
globalRoleList := &iamv1beta1.GlobalRoleList{}
if err := d.cache.List(context.Background(), globalRoleList,
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
roles = make([]*iamv1beta1.GlobalRole, 0)
for _, item := range globalRoleList.Items {
roles = append(roles, item.DeepCopy())
}
}
var result []runtime.Object
@@ -67,14 +66,13 @@ func (d *globalrolesGetter) List(_ string, query *query.Query) (*api.ListResult,
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *globalrolesGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftRole, ok := left.(*iamv1alpha2.GlobalRole)
func (d *globalRolesGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftRole, ok := left.(*iamv1beta1.GlobalRole)
if !ok {
return false
}
rightRole, ok := right.(*iamv1alpha2.GlobalRole)
rightRole, ok := right.(*iamv1beta1.GlobalRole)
if !ok {
return false
}
@@ -82,8 +80,8 @@ func (d *globalrolesGetter) compare(left runtime.Object, right runtime.Object, f
return v1alpha3.DefaultObjectMetaCompare(leftRole.ObjectMeta, rightRole.ObjectMeta, field)
}
func (d *globalrolesGetter) filter(object runtime.Object, filter query.Filter) bool {
role, ok := object.(*iamv1alpha2.GlobalRole)
func (d *globalRolesGetter) filter(object runtime.Object, filter query.Filter) bool {
role, ok := object.(*iamv1beta1.GlobalRole)
if !ok {
return false
@@ -92,8 +90,8 @@ func (d *globalrolesGetter) filter(object runtime.Object, filter query.Filter) b
return v1alpha3.DefaultObjectMetaFilter(role.ObjectMeta, filter)
}
func (d *globalrolesGetter) fetchAggregationRoles(name string) ([]*iamv1alpha2.GlobalRole, error) {
roles := make([]*iamv1alpha2.GlobalRole, 0)
func (d *globalRolesGetter) fetchAggregationRoles(name string) ([]*iamv1beta1.GlobalRole, error) {
roles := make([]*iamv1beta1.GlobalRole, 0)
obj, err := d.Get("", name)
@@ -104,7 +102,7 @@ func (d *globalrolesGetter) fetchAggregationRoles(name string) ([]*iamv1alpha2.G
return nil, err
}
if annotation := obj.(*iamv1alpha2.GlobalRole).Annotations[iamv1alpha2.AggregationRolesAnnotation]; annotation != "" {
if annotation := obj.(*iamv1beta1.GlobalRole).Annotations[iamv1beta1.AggregationRolesAnnotation]; annotation != "" {
var roleNames []string
if err = json.Unmarshal([]byte(annotation), &roleNames); err == nil {
@@ -119,7 +117,7 @@ func (d *globalrolesGetter) fetchAggregationRoles(name string) ([]*iamv1alpha2.G
return nil, err
}
roles = append(roles, role.(*iamv1alpha2.GlobalRole))
roles = append(roles, role.(*iamv1beta1.GlobalRole))
}
}
}

View File

@@ -1,113 +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 globalrole
import (
"testing"
"github.com/google/go-cmp/cmp"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
iamv1alpha2 "kubesphere.io/api/iam/v1alpha2"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
func TestListGlobalRoles(t *testing.T) {
tests := []struct {
description string
namespace string
query *query.Query
expected *api.ListResult
expectedErr error
}{
{
"test name filter",
"bar",
&query.Query{
Pagination: &query.Pagination{
Limit: 1,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{query.FieldName: query.Value("foo2")},
},
&api.ListResult{
Items: []interface{}{
foo2,
},
TotalItems: 1,
},
nil,
},
}
getter := prepare()
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
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, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
}
})
}
}
var (
foo1 = &iamv1alpha2.GlobalRole{
ObjectMeta: metav1.ObjectMeta{
Name: "foo1",
},
}
foo2 = &iamv1alpha2.GlobalRole{
ObjectMeta: metav1.ObjectMeta{
Name: "foo2",
},
}
bar1 = &iamv1alpha2.GlobalRole{
ObjectMeta: metav1.ObjectMeta{
Name: "bar1",
},
}
roles = []interface{}{foo1, foo2, bar1}
)
func prepare() v1alpha3.Interface {
client := fake.NewSimpleClientset()
informer := informers.NewSharedInformerFactory(client, 0)
for _, role := range roles {
informer.Iam().V1alpha2().GlobalRoles().Informer().GetIndexer().Add(role)
}
return New(informer)
}

View File

@@ -1,68 +1,57 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package globalrolebinding
import (
"k8s.io/apimachinery/pkg/runtime"
"context"
iamv1alpha2 "kubesphere.io/api/iam/v1alpha2"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
iamv1beta1 "kubesphere.io/api/iam/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type globalrolebindingsGetter struct {
sharedInformers informers.SharedInformerFactory
type globalRoleBindingsGetter struct {
cache runtimeclient.Reader
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &globalrolebindingsGetter{sharedInformers: sharedInformers}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &globalRoleBindingsGetter{cache: cache}
}
func (d *globalrolebindingsGetter) Get(_, name string) (runtime.Object, error) {
return d.sharedInformers.Iam().V1alpha2().GlobalRoleBindings().Lister().Get(name)
func (d *globalRoleBindingsGetter) Get(_, name string) (runtime.Object, error) {
globalRoleBinding := &iamv1beta1.GlobalRoleBinding{}
return globalRoleBinding, d.cache.Get(context.Background(), types.NamespacedName{Name: name}, globalRoleBinding)
}
func (d *globalrolebindingsGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
globalRoleBindings, err := d.sharedInformers.Iam().V1alpha2().GlobalRoleBindings().Lister().List(query.Selector())
if err != nil {
func (d *globalRoleBindingsGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
globalRoleBindings := &iamv1beta1.GlobalRoleBindingList{}
if err := d.cache.List(context.Background(), globalRoleBindings,
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
for _, globalRoleBinding := range globalRoleBindings {
result = append(result, globalRoleBinding)
for _, item := range globalRoleBindings.Items {
result = append(result, item.DeepCopy())
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *globalrolebindingsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftRoleBinding, ok := left.(*iamv1alpha2.GlobalRoleBinding)
func (d *globalRoleBindingsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftRoleBinding, ok := left.(*iamv1beta1.GlobalRoleBinding)
if !ok {
return false
}
rightRoleBinding, ok := right.(*iamv1alpha2.GlobalRoleBinding)
rightRoleBinding, ok := right.(*iamv1beta1.GlobalRoleBinding)
if !ok {
return false
}
@@ -70,8 +59,8 @@ func (d *globalrolebindingsGetter) compare(left runtime.Object, right runtime.Ob
return v1alpha3.DefaultObjectMetaCompare(leftRoleBinding.ObjectMeta, rightRoleBinding.ObjectMeta, field)
}
func (d *globalrolebindingsGetter) filter(object runtime.Object, filter query.Filter) bool {
role, ok := object.(*iamv1alpha2.GlobalRoleBinding)
func (d *globalRoleBindingsGetter) filter(object runtime.Object, filter query.Filter) bool {
role, ok := object.(*iamv1beta1.GlobalRoleBinding)
if !ok {
return false

View File

@@ -1,114 +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 globalrolebinding
import (
"testing"
"github.com/google/go-cmp/cmp"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
iamv1alpha2 "kubesphere.io/api/iam/v1alpha2"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
func TestListRoles(t *testing.T) {
tests := []struct {
description string
query *query.Query
expected *api.ListResult
expectedErr error
}{
{
"test name filter",
&query.Query{
Pagination: &query.Pagination{
Limit: 1,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{query.FieldName: query.Value("foo2")},
},
&api.ListResult{
Items: []interface{}{
foo2,
},
TotalItems: 1,
},
nil,
},
}
getter := prepare()
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
got, err := getter.List("", 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, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
}
})
}
}
var (
foo1 = &iamv1alpha2.GlobalRoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "foo1",
Namespace: "bar",
},
}
foo2 = &iamv1alpha2.GlobalRoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "foo2",
Namespace: "bar",
},
}
bar1 = &iamv1alpha2.GlobalRoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "bar1",
Namespace: "bar",
},
}
globalRoleBindings = []interface{}{foo1, foo2, bar1}
)
func prepare() v1alpha3.Interface {
client := fake.NewSimpleClientset()
informer := informers.NewSharedInformerFactory(client, 0)
for _, globalRoleBinding := range globalRoleBindings {
informer.Iam().V1alpha2().GlobalRoleBindings().Informer().GetIndexer().Add(globalRoleBinding)
}
return New(informer)
}

View File

@@ -1,67 +1,57 @@
/*
Copyright 2020 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 group
import (
"k8s.io/apimachinery/pkg/runtime"
"context"
"kubesphere.io/api/iam/v1alpha2"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
iamv1beta1 "kubesphere.io/api/iam/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type groupGetter struct {
sharedInformers informers.SharedInformerFactory
cache runtimeclient.Reader
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &groupGetter{sharedInformers: sharedInformers}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &groupGetter{cache: cache}
}
func (d *groupGetter) Get(_, name string) (runtime.Object, error) {
return d.sharedInformers.Iam().V1alpha2().Groups().Lister().Get(name)
group := &iamv1beta1.Group{}
return group, d.cache.Get(context.Background(), types.NamespacedName{Name: name}, group)
}
func (d *groupGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
groups, err := d.sharedInformers.Iam().V1alpha2().Groups().Lister().List(query.Selector())
if err != nil {
groups := &iamv1beta1.GroupList{}
if err := d.cache.List(context.Background(), groups,
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
for _, group := range groups {
result = append(result, group)
for _, item := range groups.Items {
result = append(result, item.DeepCopy())
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *groupGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftGroup, ok := left.(*v1alpha2.Group)
leftGroup, ok := left.(*iamv1beta1.Group)
if !ok {
return false
}
rightGroup, ok := right.(*v1alpha2.Group)
rightGroup, ok := right.(*iamv1beta1.Group)
if !ok {
return false
}
@@ -70,7 +60,7 @@ func (d *groupGetter) compare(left runtime.Object, right runtime.Object, field q
}
func (d *groupGetter) filter(object runtime.Object, filter query.Filter) bool {
group, ok := object.(*v1alpha2.Group)
group, ok := object.(*iamv1beta1.Group)
if !ok {
return false

View File

@@ -1,113 +0,0 @@
/*
Copyright 2020 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 group
import (
"testing"
"github.com/google/go-cmp/cmp"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"kubesphere.io/api/iam/v1alpha2"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
func TestListWorkspaces(t *testing.T) {
tests := []struct {
description string
namespace string
query *query.Query
expected *api.ListResult
expectedErr error
}{
{
"test name filter",
"bar",
&query.Query{
Pagination: &query.Pagination{
Limit: 1,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{query.FieldName: query.Value("foo2")},
},
&api.ListResult{
Items: []interface{}{
foo2,
},
TotalItems: 1,
},
nil,
},
}
getter := prepare()
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
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, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
}
})
}
}
var (
foo1 = &v1alpha2.Group{
ObjectMeta: metav1.ObjectMeta{
Name: "foo1",
},
}
foo2 = &v1alpha2.Group{
ObjectMeta: metav1.ObjectMeta{
Name: "foo2",
},
}
bar1 = &v1alpha2.Group{
ObjectMeta: metav1.ObjectMeta{
Name: "bar1",
},
}
groups = []interface{}{foo1, foo2, bar1}
)
func prepare() v1alpha3.Interface {
client := fake.NewSimpleClientset()
informer := informers.NewSharedInformerFactory(client, 0)
for _, group := range groups {
informer.Iam().V1alpha2().Groups().Informer().GetIndexer().Add(group)
}
return New(informer)
}

View File

@@ -1,29 +1,21 @@
/*
Copyright 2020 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 groupbinding
import (
"k8s.io/apimachinery/pkg/runtime"
"context"
"kubesphere.io/api/iam/v1alpha2"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
iamv1beta1 "kubesphere.io/api/iam/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
)
@@ -31,40 +23,38 @@ import (
const User = "user"
type groupBindingGetter struct {
sharedInformers informers.SharedInformerFactory
cache runtimeclient.Reader
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &groupBindingGetter{sharedInformers: sharedInformers}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &groupBindingGetter{cache: cache}
}
func (d *groupBindingGetter) Get(_, name string) (runtime.Object, error) {
return d.sharedInformers.Iam().V1alpha2().GroupBindings().Lister().Get(name)
groupBinding := &iamv1beta1.GroupBinding{}
return groupBinding, d.cache.Get(context.Background(), types.NamespacedName{Name: name}, groupBinding)
}
func (d *groupBindingGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
groupBindings, err := d.sharedInformers.Iam().V1alpha2().GroupBindings().Lister().List(query.Selector())
if err != nil {
groupBindings := &iamv1beta1.GroupBindingList{}
if err := d.cache.List(context.Background(), groupBindings,
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
for _, groupBinding := range groupBindings {
result = append(result, groupBinding)
for _, item := range groupBindings.Items {
result = append(result, item.DeepCopy())
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *groupBindingGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftGroupBinding, ok := left.(*v1alpha2.GroupBinding)
leftGroupBinding, ok := left.(*iamv1beta1.GroupBinding)
if !ok {
return false
}
rightGroupBinding, ok := right.(*v1alpha2.GroupBinding)
rightGroupBinding, ok := right.(*iamv1beta1.GroupBinding)
if !ok {
return false
}
@@ -73,16 +63,15 @@ func (d *groupBindingGetter) compare(left runtime.Object, right runtime.Object,
}
func (d *groupBindingGetter) filter(object runtime.Object, filter query.Filter) bool {
groupbinding, ok := object.(*v1alpha2.GroupBinding)
groupBinding, ok := object.(*iamv1beta1.GroupBinding)
if !ok {
return false
}
switch filter.Field {
case User:
return sliceutil.HasString(groupbinding.Users, string(filter.Value))
return sliceutil.HasString(groupBinding.Users, string(filter.Value))
default:
return v1alpha3.DefaultObjectMetaFilter(groupbinding.ObjectMeta, filter)
return v1alpha3.DefaultObjectMetaFilter(groupBinding.ObjectMeta, filter)
}
}

View File

@@ -1,113 +0,0 @@
/*
Copyright 2020 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 groupbinding
import (
"testing"
"github.com/google/go-cmp/cmp"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"kubesphere.io/api/iam/v1alpha2"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
func TestListWorkspaces(t *testing.T) {
tests := []struct {
description string
namespace string
query *query.Query
expected *api.ListResult
expectedErr error
}{
{
"test name filter",
"bar",
&query.Query{
Pagination: &query.Pagination{
Limit: 1,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{query.FieldName: query.Value("foo2")},
},
&api.ListResult{
Items: []interface{}{
foo2,
},
TotalItems: 1,
},
nil,
},
}
getter := prepare()
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
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, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
}
})
}
}
var (
foo1 = &v1alpha2.GroupBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "foo1",
},
}
foo2 = &v1alpha2.GroupBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "foo2",
},
}
bar1 = &v1alpha2.GroupBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "bar1",
},
}
groupBindings = []interface{}{foo1, foo2, bar1}
)
func prepare() v1alpha3.Interface {
client := fake.NewSimpleClientset()
informer := informers.NewSharedInformerFactory(client, 0)
for _, groupBinding := range groupBindings {
informer.Iam().V1alpha2().GroupBindings().Informer().GetIndexer().Add(groupBinding)
}
return New(informer)
}

View File

@@ -0,0 +1,109 @@
/*
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package hpa
import (
"context"
"github.com/Masterminds/semver/v3"
autoscalingv2 "k8s.io/api/autoscaling/v2"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
"kubesphere.io/kubesphere/pkg/scheme"
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
)
type hpaGetter struct {
cache runtimeclient.Reader
gvk schema.GroupVersionKind
listGVK schema.GroupVersionKind
}
func New(cache runtimeclient.Reader, k8sVersion *semver.Version) v1alpha3.Interface {
gvk := autoscalingv2.SchemeGroupVersion.WithKind("HorizontalPodAutoscaler")
listGVK := schema.GroupVersionKind{
Group: gvk.Group,
Version: gvk.Version,
Kind: gvk.Kind + "List",
}
if k8sutil.ServeAutoscalingV2beta2(k8sVersion) {
gvk.Version = "v2beta2"
listGVK.Version = "v2beta2"
}
return &hpaGetter{
cache: cache,
gvk: gvk,
listGVK: listGVK,
}
}
func (s *hpaGetter) Get(namespace, name string) (runtime.Object, error) {
obj, err := scheme.Scheme.New(s.gvk)
if err != nil {
return nil, err
}
hpa := obj.(client.Object)
return hpa, s.cache.Get(context.Background(), types.NamespacedName{Namespace: namespace, Name: name}, hpa)
}
func (s *hpaGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
listObj := &unstructured.UnstructuredList{}
listObj.SetGroupVersionKind(s.listGVK)
if err := s.cache.List(context.Background(), listObj, client.InNamespace(namespace),
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
if err := listObj.EachListItem(func(object runtime.Object) error {
result = append(result, object)
return nil
}); err != nil {
return nil, err
}
return v1alpha3.DefaultList(result, query, s.compare, s.filter), nil
}
func (s *hpaGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftHPA, ok := left.(*unstructured.Unstructured)
if !ok {
return false
}
rightHPA, ok := right.(*unstructured.Unstructured)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaCompare(k8sutil.GetObjectMeta(leftHPA), k8sutil.GetObjectMeta(rightHPA), field)
}
func (s *hpaGetter) filter(object runtime.Object, filter query.Filter) bool {
hpa, ok := object.(*unstructured.Unstructured)
if !ok {
return false
}
targetKind, _, _ := unstructured.NestedString(hpa.UnstructuredContent(), "spec", "scaleTargetRef", "kind")
targetName, _, _ := unstructured.NestedString(hpa.UnstructuredContent(), "spec", "scaleTargetRef", "name")
switch filter.Field {
case "targetKind":
return targetKind == string(filter.Value)
case "targetName":
return targetName == string(filter.Value)
default:
return v1alpha3.DefaultObjectMetaFilter(k8sutil.GetObjectMeta(hpa), filter)
}
}

View File

@@ -1,25 +1,18 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package ingress
import (
"context"
v1 "k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
@@ -27,34 +20,32 @@ import (
)
type ingressGetter struct {
sharedInformers informers.SharedInformerFactory
cache runtimeclient.Reader
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &ingressGetter{sharedInformers: sharedInformers}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &ingressGetter{cache: cache}
}
func (g *ingressGetter) Get(namespace, name string) (runtime.Object, error) {
return g.sharedInformers.Networking().V1().Ingresses().Lister().Ingresses(namespace).Get(name)
ingress := &v1.Ingress{}
return ingress, g.cache.Get(context.Background(), types.NamespacedName{Namespace: namespace, Name: name}, ingress)
}
func (g *ingressGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
// first retrieves all deployments within given namespace
ingresses, err := g.sharedInformers.Networking().V1().Ingresses().Lister().Ingresses(namespace).List(query.Selector())
if err != nil {
ingresses := &v1.IngressList{}
if err := g.cache.List(context.Background(), ingresses, client.InNamespace(namespace),
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
for _, ingress := range ingresses {
result = append(result, ingress)
for _, item := range ingresses.Items {
result = append(result, item.DeepCopy())
}
return v1alpha3.DefaultList(result, query, g.compare, g.filter), nil
}
func (g *ingressGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftIngress, ok := left.(*v1.Ingress)
if !ok {
return false

View File

@@ -1,116 +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 ingress
import (
"testing"
"github.com/google/go-cmp/cmp"
v1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
func TestListIngresses(t *testing.T) {
tests := []struct {
description string
namespace string
query *query.Query
expected *api.ListResult
expectedErr error
}{
{
"test name filter",
"bar",
&query.Query{
Pagination: &query.Pagination{
Limit: 1,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{query.FieldName: query.Value("foo2")},
},
&api.ListResult{
Items: []interface{}{
foo2,
},
TotalItems: 1,
},
nil,
},
}
getter := prepare()
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
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, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
}
})
}
}
var (
foo1 = &v1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "foo1",
Namespace: "bar",
},
}
foo2 = &v1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "foo2",
Namespace: "bar",
},
}
bar1 = &v1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "bar1",
Namespace: "bar",
},
}
ingresses = []interface{}{foo1, foo2, bar1}
)
func prepare() v1alpha3.Interface {
client := fake.NewSimpleClientset()
informer := informers.NewSharedInformerFactory(client, 0)
for _, ingress := range ingresses {
informer.Networking().V1().Ingresses().Informer().GetIndexer().Add(ingress)
}
return New(informer)
}

View File

@@ -1,18 +1,7 @@
/*
Copyright 2020 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 v1alpha3
@@ -20,14 +9,16 @@ import (
"sort"
"strings"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"kubesphere.io/kubesphere/pkg/constants"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/constants"
)
type Interface interface {
@@ -38,7 +29,7 @@ type Interface interface {
List(namespace string, query *query.Query) (*api.ListResult, error)
}
// CompareFunc return true is left great than right
// CompareFunc return true is left greater than right
type CompareFunc func(runtime.Object, runtime.Object, query.Field) bool
type FilterFunc func(runtime.Object, query.Filter) bool
@@ -47,7 +38,7 @@ type TransformFunc func(runtime.Object) runtime.Object
func DefaultList(objects []runtime.Object, q *query.Query, compareFunc CompareFunc, filterFunc FilterFunc, transformFuncs ...TransformFunc) *api.ListResult {
// selected matched ones
var filtered []runtime.Object
filtered := make([]runtime.Object, 0)
for _, object := range objects {
selected := true
for field, value := range q.Filters {
@@ -83,11 +74,11 @@ func DefaultList(objects []runtime.Object, q *query.Query, compareFunc CompareFu
return &api.ListResult{
TotalItems: len(filtered),
Items: objectsToInterfaces(filtered[start:end]),
Items: filtered[start:end],
}
}
// DefaultObjectMetaCompare return true is left great than right
// DefaultObjectMetaCompare return true is left greater than right
func DefaultObjectMetaCompare(left, right metav1.ObjectMeta, sortBy query.Field) bool {
switch sortBy {
// ?sortBy=name
@@ -107,7 +98,7 @@ func DefaultObjectMetaCompare(left, right metav1.ObjectMeta, sortBy query.Field)
}
}
// Default metadata filter
// DefaultObjectMetaFilter is default metadata filter
func DefaultObjectMetaFilter(item metav1.ObjectMeta, filter query.Filter) bool {
switch filter.Field {
case query.FieldNames:
@@ -119,20 +110,18 @@ func DefaultObjectMetaFilter(item metav1.ObjectMeta, filter query.Filter) bool {
return false
// /namespaces?page=1&limit=10&name=default
case query.FieldName:
return strings.Contains(item.Name, string(filter.Value))
// /clusters?page=1&limit=10&alias=xxx
case query.FieldAlias:
if item.Annotations == nil {
return false
displayName := item.GetAnnotations()[constants.DisplayNameAnnotationKey]
if displayName != "" && strings.Contains(displayName, string(filter.Value)) {
return true
}
return strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], string(filter.Value))
// /namespaces?page=1&limit=10&uid=a8a8d6cf-f6a5-4fea-9c1b-e57610115706
return strings.Contains(item.GetName(), string(filter.Value))
// /namespaces?page=1&limit=10&uid=a8a8d6cf-f6a5-4fea-9c1b-e57610115706
case query.FieldUID:
return strings.Compare(string(item.UID), string(filter.Value)) == 0
// /deployments?page=1&limit=10&namespace=kubesphere-system
// /deployments?page=1&limit=10&namespace=kubesphere-system
case query.FieldNamespace:
return strings.Compare(item.Namespace, string(filter.Value)) == 0
// /namespaces?page=1&limit=10&ownerReference=a8a8d6cf-f6a5-4fea-9c1b-e57610115706
// /namespaces?page=1&limit=10&ownerReference=a8a8d6cf-f6a5-4fea-9c1b-e57610115706
case query.FieldOwnerReference:
for _, ownerReference := range item.OwnerReferences {
if strings.Compare(string(ownerReference.UID), string(filter.Value)) == 0 {
@@ -140,7 +129,7 @@ func DefaultObjectMetaFilter(item metav1.ObjectMeta, filter query.Filter) bool {
}
}
return false
// /namespaces?page=1&limit=10&ownerKind=Workspace
// /namespaces?page=1&limit=10&ownerKind=Workspace
case query.FieldOwnerKind:
for _, ownerReference := range item.OwnerReferences {
if strings.Compare(ownerReference.Kind, string(filter.Value)) == 0 {
@@ -148,14 +137,15 @@ func DefaultObjectMetaFilter(item metav1.ObjectMeta, filter query.Filter) bool {
}
}
return false
// /namespaces?page=1&limit=10&annotation=openpitrix_runtime
// /namespaces?page=1&limit=10&annotation=openpitrix_runtime
case query.FieldAnnotation:
return labelMatch(item.Annotations, string(filter.Value))
// /namespaces?page=1&limit=10&label=kubesphere.io/workspace:system-workspace
// /namespaces?page=1&limit=10&label=kubesphere.io/workspace:system-workspace
case query.FieldLabel:
return labelMatch(item.Labels, string(filter.Value))
// not supported filter
default:
return false
return true
}
}
@@ -167,11 +157,3 @@ func labelMatch(m map[string]string, filter string) bool {
}
return labelSelector.Matches(labels.Set(m))
}
func objectsToInterfaces(objs []runtime.Object) []interface{} {
res := make([]interface{}, 0)
for _, obj := range objs {
res = append(res, obj)
}
return res
}

View File

@@ -1,20 +1,7 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package v1alpha3

View File

@@ -1,117 +0,0 @@
/*
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 ippool
import (
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
k8sinformers "k8s.io/client-go/informers"
networkv1alpha1 "kubesphere.io/api/network/v1alpha1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type ippoolGetter struct {
informers informers.SharedInformerFactory
k8sInformers k8sinformers.SharedInformerFactory
}
func New(informers informers.SharedInformerFactory, k8sInformers k8sinformers.SharedInformerFactory) v1alpha3.Interface {
return &ippoolGetter{
informers: informers,
k8sInformers: k8sInformers,
}
}
func (n ippoolGetter) Get(namespace, name string) (runtime.Object, error) {
return n.informers.Network().V1alpha1().IPPools().Lister().Get(name)
}
func (n ippoolGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
var result []runtime.Object
if namespace != "" {
workspace := ""
ns, err := n.k8sInformers.Core().V1().Namespaces().Lister().Get(namespace)
if err != nil {
return nil, err
}
if ns.Labels != nil {
workspace = ns.Labels[constants.WorkspaceLabelKey]
}
ps, err := n.informers.Network().V1alpha1().IPPools().Lister().List(labels.SelectorFromSet(
map[string]string{
networkv1alpha1.IPPoolDefaultLabel: "",
}))
if err != nil {
return nil, err
}
for _, p := range ps {
result = append(result, p)
}
if workspace != "" {
query.LabelSelector = labels.SelectorFromSet(
map[string]string{
constants.WorkspaceLabelKey: workspace,
}).String()
ps, err := n.informers.Network().V1alpha1().IPPools().Lister().List(query.Selector())
if err != nil {
return nil, err
}
for _, p := range ps {
result = append(result, p)
}
}
} else {
ps, err := n.informers.Network().V1alpha1().IPPools().Lister().List(labels.Everything())
if err != nil {
return nil, err
}
for _, p := range ps {
result = append(result, p)
}
}
return v1alpha3.DefaultList(result, query, n.compare, n.filter), nil
}
func (n ippoolGetter) filter(item runtime.Object, filter query.Filter) bool {
p, ok := item.(*networkv1alpha1.IPPool)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaFilter(p.ObjectMeta, filter)
}
func (n ippoolGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftP, ok := left.(*networkv1alpha1.IPPool)
if !ok {
return false
}
rightP, ok := right.(*networkv1alpha1.IPPool)
if !ok {
return true
}
return v1alpha3.DefaultObjectMetaCompare(leftP.ObjectMeta, rightP.ObjectMeta, field)
}

View File

@@ -1,152 +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 ippool
import (
"testing"
"github.com/google/go-cmp/cmp"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8sinformers "k8s.io/client-go/informers"
k8sfake "k8s.io/client-go/kubernetes/fake"
"kubesphere.io/api/network/v1alpha1"
tenantv1alpha1 "kubesphere.io/api/tenant/v1alpha1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
func TestListIPPools(t *testing.T) {
tests := []struct {
description string
namespace string
query *query.Query
expected *api.ListResult
expectedErr error
}{
{
"test name filter",
"",
&query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{
query.FieldName: query.Value("foo2"),
},
},
&api.ListResult{
Items: []interface{}{foo2},
TotalItems: 1,
},
nil,
},
{
"test namespace filter",
"ns1",
&query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
},
&api.ListResult{
Items: []interface{}{foo1},
TotalItems: 1,
},
nil,
},
}
getter := prepare()
for _, test := range tests {
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, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
}
}
}
var (
foo1 = &v1alpha1.IPPool{
ObjectMeta: metav1.ObjectMeta{
Name: "foo1",
Labels: map[string]string{
constants.WorkspaceLabelKey: "wk1",
},
},
}
foo2 = &v1alpha1.IPPool{
ObjectMeta: metav1.ObjectMeta{
Name: "foo2",
},
}
foo3 = &v1alpha1.IPPool{
ObjectMeta: metav1.ObjectMeta{
Name: "foo3",
},
}
ns = &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "ns1",
Labels: map[string]string{
constants.WorkspaceLabelKey: "wk1",
},
},
}
wk = &tenantv1alpha1.Workspace{
ObjectMeta: metav1.ObjectMeta{
Name: "wk1",
},
}
ps = []interface{}{foo1, foo2, foo3}
)
func prepare() v1alpha3.Interface {
client := fake.NewSimpleClientset()
k8sClient := k8sfake.NewSimpleClientset()
informer := informers.NewSharedInformerFactory(client, 0)
k8sInformer := k8sinformers.NewSharedInformerFactory(k8sClient, 0)
for _, p := range ps {
informer.Network().V1alpha1().IPPools().Informer().GetIndexer().Add(p)
}
informer.Tenant().V1alpha1().Workspaces().Informer().GetIndexer().Add(wk)
k8sInformer.Core().V1().Namespaces().Informer().GetIndexer().Add(ns)
return New(informer, k8sInformer)
}

View File

@@ -1,29 +1,22 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package job
import (
"context"
"strings"
"time"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
@@ -37,33 +30,32 @@ const (
)
type jobsGetter struct {
sharedInformers informers.SharedInformerFactory
cache runtimeclient.Reader
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &jobsGetter{sharedInformers: sharedInformers}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &jobsGetter{cache: cache}
}
func (d *jobsGetter) Get(namespace, name string) (runtime.Object, error) {
return d.sharedInformers.Batch().V1().Jobs().Lister().Jobs(namespace).Get(name)
job := &batchv1.Job{}
return job, d.cache.Get(context.Background(), types.NamespacedName{Namespace: namespace, Name: name}, job)
}
func (d *jobsGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
jobs, err := d.sharedInformers.Batch().V1().Jobs().Lister().Jobs(namespace).List(query.Selector())
if err != nil {
jobs := &batchv1.JobList{}
if err := d.cache.List(context.Background(), jobs, client.InNamespace(namespace),
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
for _, job := range jobs {
result = append(result, job)
for _, item := range jobs.Items {
result = append(result, item.DeepCopy())
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *jobsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftJob, ok := left.(*batchv1.Job)
if !ok {
return false
@@ -108,7 +100,6 @@ func jobStatus(status batchv1.JobStatus) string {
return jobFailed
}
}
return jobRunning
}

View File

@@ -0,0 +1,75 @@
/*
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package label
import (
"context"
"strings"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
clusterv1alpha1 "kubesphere.io/api/cluster/v1alpha1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type labelsGetter struct {
cache runtimeclient.Reader
}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &labelsGetter{cache: cache}
}
func (n labelsGetter) Get(_, name string) (runtime.Object, error) {
label := &clusterv1alpha1.Label{}
return label, n.cache.Get(context.Background(), types.NamespacedName{Name: name}, label)
}
func (n labelsGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
labels := &clusterv1alpha1.LabelList{}
if err := n.cache.List(context.Background(), labels, client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
for _, item := range labels.Items {
result = append(result, item.DeepCopy())
}
return v1alpha3.DefaultList(result, query, n.compare, n.filter), nil
}
func (n labelsGetter) filter(item runtime.Object, filter query.Filter) bool {
label, ok := item.(*clusterv1alpha1.Label)
if !ok {
return false
}
switch filter.Field {
case query.FieldName:
return strings.Contains(label.Spec.Key, string(filter.Value)) || strings.Contains(label.Spec.Value, string(filter.Value))
default:
return false
}
}
func (n labelsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftLabel, ok := left.(*clusterv1alpha1.Label)
if !ok {
return false
}
rightLabel, ok := right.(*clusterv1alpha1.Label)
if !ok {
return true
}
return v1alpha3.DefaultObjectMetaCompare(leftLabel.ObjectMeta, rightLabel.ObjectMeta, field)
}

View File

@@ -1,79 +1,68 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package loginrecord
import (
"k8s.io/apimachinery/pkg/runtime"
"context"
iamv1alpha2 "kubesphere.io/api/iam/v1alpha2"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
iamv1beta1 "kubesphere.io/api/iam/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"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"
)
const recordType = "type"
type loginrecordsGetter struct {
ksInformer ksinformers.SharedInformerFactory
type loginRecordsGetter struct {
cache runtimeclient.Reader
}
func New(ksinformer ksinformers.SharedInformerFactory) v1alpha3.Interface {
return &loginrecordsGetter{ksInformer: ksinformer}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &loginRecordsGetter{cache: cache}
}
func (d *loginrecordsGetter) Get(_, name string) (runtime.Object, error) {
return d.ksInformer.Iam().V1alpha2().Users().Lister().Get(name)
func (d *loginRecordsGetter) Get(_, name string) (runtime.Object, error) {
loginRecord := &iamv1beta1.LoginRecord{}
return loginRecord, d.cache.Get(context.Background(), types.NamespacedName{Name: name}, loginRecord)
}
func (d *loginrecordsGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
records, err := d.ksInformer.Iam().V1alpha2().LoginRecords().Lister().List(query.Selector())
if err != nil {
func (d *loginRecordsGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
loginRecords := &iamv1beta1.LoginRecordList{}
if err := d.cache.List(context.Background(), loginRecords,
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
for _, user := range records {
result = append(result, user)
for _, item := range loginRecords.Items {
result = append(result, item.DeepCopy())
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *loginrecordsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftUser, ok := left.(*iamv1alpha2.LoginRecord)
func (d *loginRecordsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftRecord, ok := left.(*iamv1beta1.LoginRecord)
if !ok {
return false
}
rightUser, ok := right.(*iamv1alpha2.LoginRecord)
rightRecord, ok := right.(*iamv1beta1.LoginRecord)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaCompare(leftUser.ObjectMeta, rightUser.ObjectMeta, field)
return v1alpha3.DefaultObjectMetaCompare(leftRecord.ObjectMeta, rightRecord.ObjectMeta, field)
}
func (d *loginrecordsGetter) filter(object runtime.Object, filter query.Filter) bool {
record, ok := object.(*iamv1alpha2.LoginRecord)
func (d *loginRecordsGetter) filter(object runtime.Object, filter query.Filter) bool {
record, ok := object.(*iamv1beta1.LoginRecord)
if !ok {
return false

View File

@@ -1,113 +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 loginrecord
import (
"testing"
"github.com/google/go-cmp/cmp"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
iamv1alpha2 "kubesphere.io/api/iam/v1alpha2"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
func TestListLoginRecords(t *testing.T) {
tests := []struct {
description string
namespace string
query *query.Query
expected *api.ListResult
expectedErr error
}{
{
"test name filter",
"bar",
&query.Query{
Pagination: &query.Pagination{
Limit: 1,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{query.FieldName: query.Value("foo2")},
},
&api.ListResult{
Items: []interface{}{
foo2,
},
TotalItems: 1,
},
nil,
},
}
getter := prepare()
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
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, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
}
})
}
}
var (
foo1 = &iamv1alpha2.LoginRecord{
ObjectMeta: metav1.ObjectMeta{
Name: "foo1",
},
}
foo2 = &iamv1alpha2.LoginRecord{
ObjectMeta: metav1.ObjectMeta{
Name: "foo2",
},
}
bar1 = &iamv1alpha2.LoginRecord{
ObjectMeta: metav1.ObjectMeta{
Name: "bar1",
},
}
records = []interface{}{foo1, foo2, bar1}
)
func prepare() v1alpha3.Interface {
client := fake.NewSimpleClientset()
informer := informers.NewSharedInformerFactory(client, 0)
for _, record := range records {
informer.Iam().V1alpha2().LoginRecords().Informer().GetIndexer().Add(record)
}
return New(informer)
}

View File

@@ -1,27 +1,19 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package namespace
import (
"context"
"strings"
v1 "k8s.io/api/core/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
@@ -29,33 +21,32 @@ import (
)
type namespacesGetter struct {
informers informers.SharedInformerFactory
cache runtimeclient.Reader
}
func New(informers informers.SharedInformerFactory) v1alpha3.Interface {
return &namespacesGetter{informers: informers}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &namespacesGetter{cache: cache}
}
func (n namespacesGetter) Get(_, name string) (runtime.Object, error) {
return n.informers.Core().V1().Namespaces().Lister().Get(name)
namespace := &corev1.Namespace{}
return namespace, n.cache.Get(context.Background(), types.NamespacedName{Name: name}, namespace)
}
func (n namespacesGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
ns, err := n.informers.Core().V1().Namespaces().Lister().List(query.Selector())
if err != nil {
namespaces := &corev1.NamespaceList{}
if err := n.cache.List(context.Background(), namespaces, client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
for _, item := range ns {
result = append(result, item)
for _, item := range namespaces.Items {
result = append(result, item.DeepCopy())
}
return v1alpha3.DefaultList(result, query, n.compare, n.filter), nil
}
func (n namespacesGetter) filter(item runtime.Object, filter query.Filter) bool {
namespace, ok := item.(*v1.Namespace)
namespace, ok := item.(*corev1.Namespace)
if !ok {
return false
}
@@ -68,12 +59,12 @@ func (n namespacesGetter) filter(item runtime.Object, filter query.Filter) bool
}
func (n namespacesGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftNs, ok := left.(*v1.Namespace)
leftNs, ok := left.(*corev1.Namespace)
if !ok {
return false
}
rightNs, ok := right.(*v1.Namespace)
rightNs, ok := right.(*corev1.Namespace)
if !ok {
return true
}

View File

@@ -1,17 +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 namespace

View File

@@ -1,75 +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 networkpolicy
import (
v1 "k8s.io/api/networking/v1"
"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"
)
type networkpolicyGetter struct {
informers informers.SharedInformerFactory
}
func New(informers informers.SharedInformerFactory) v1alpha3.Interface {
return &networkpolicyGetter{informers: informers}
}
func (n networkpolicyGetter) Get(namespace, name string) (runtime.Object, error) {
return n.informers.Networking().V1().NetworkPolicies().Lister().NetworkPolicies(namespace).Get(name)
}
func (n networkpolicyGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
nps, err := n.informers.Networking().V1().NetworkPolicies().Lister().NetworkPolicies(namespace).List(query.Selector())
if err != nil {
return nil, err
}
var result []runtime.Object
for _, item := range nps {
result = append(result, item)
}
return v1alpha3.DefaultList(result, query, n.compare, n.filter), nil
}
func (n networkpolicyGetter) filter(item runtime.Object, filter query.Filter) bool {
np, ok := item.(*v1.NetworkPolicy)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaFilter(np.ObjectMeta, filter)
}
func (n networkpolicyGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftNP, ok := left.(*v1.NetworkPolicy)
if !ok {
return false
}
rightNP, ok := right.(*v1.NetworkPolicy)
if !ok {
return true
}
return v1alpha3.DefaultObjectMetaCompare(leftNP.ObjectMeta, rightNP.ObjectMeta, field)
}

View File

@@ -1,111 +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 networkpolicy
import (
"testing"
"github.com/google/go-cmp/cmp"
netv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
func TestListNetworkPolicies(t *testing.T) {
tests := []struct {
description string
namespace string
query *query.Query
expected *api.ListResult
expectedErr error
}{
{
"test name filter",
"default",
&query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{
query.FieldNamespace: query.Value("default"),
},
},
&api.ListResult{
Items: []interface{}{foo3, foo2, foo1},
TotalItems: len(networkpolicies),
},
nil,
},
}
getter := prepare()
for _, test := range tests {
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, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
}
}
}
var (
foo1 = &netv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "foo1",
Namespace: "default",
},
}
foo2 = &netv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "foo2",
Namespace: "default",
},
}
foo3 = &netv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "foo3",
Namespace: "default",
},
}
networkpolicies = []interface{}{foo1, foo2, foo3}
)
func prepare() v1alpha3.Interface {
client := fake.NewSimpleClientset()
informer := informers.NewSharedInformerFactory(client, 0)
for _, networkpolicy := range networkpolicies {
informer.Networking().V1().NetworkPolicies().Informer().GetIndexer().Add(networkpolicy)
}
return New(informer)
}

View File

@@ -1,31 +1,18 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package node
import (
"fmt"
"sort"
"context"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/labels"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
resourceheper "k8s.io/kubectl/pkg/util/resource"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
@@ -34,123 +21,54 @@ import (
// Those annotations were added to node only for display purposes
const (
nodeCPURequests = "node.kubesphere.io/cpu-requests"
nodeMemoryRequests = "node.kubesphere.io/memory-requests"
nodeCPULimits = "node.kubesphere.io/cpu-limits"
nodeMemoryLimits = "node.kubesphere.io/memory-limits"
nodeCPURequestsFraction = "node.kubesphere.io/cpu-requests-fraction"
nodeCPULimitsFraction = "node.kubesphere.io/cpu-limits-fraction"
nodeMemoryRequestsFraction = "node.kubesphere.io/memory-requests-fraction"
nodeMemoryLimitsFraction = "node.kubesphere.io/memory-limits-fraction"
nodeConfigOK v1.NodeConditionType = "ConfigOK"
nodeKubeletReady v1.NodeConditionType = "KubeletReady"
statusRunning = "running"
statusWarning = "warning"
statusUnschedulable = "unschedulable"
nodeCPURequests = "node.kubesphere.io/cpu-requests"
nodeMemoryRequests = "node.kubesphere.io/memory-requests"
nodeCPULimits = "node.kubesphere.io/cpu-limits"
nodeMemoryLimits = "node.kubesphere.io/memory-limits"
nodeCPURequestsFraction = "node.kubesphere.io/cpu-requests-fraction"
nodeCPULimitsFraction = "node.kubesphere.io/cpu-limits-fraction"
nodeMemoryRequestsFraction = "node.kubesphere.io/memory-requests-fraction"
nodeMemoryLimitsFraction = "node.kubesphere.io/memory-limits-fraction"
nodeConfigOK corev1.NodeConditionType = "ConfigOK"
nodeKubeletReady corev1.NodeConditionType = "KubeletReady"
statusRunning = "running"
statusWarning = "warning"
statusUnschedulable = "unschedulable"
)
type nodesGetter struct {
informers informers.SharedInformerFactory
cache runtimeclient.Reader
}
func New(informers informers.SharedInformerFactory) v1alpha3.Interface {
return &nodesGetter{
informers: informers,
}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &nodesGetter{cache: cache}
}
func (c *nodesGetter) Get(_, name string) (runtime.Object, error) {
node, err := c.informers.Core().V1().Nodes().Lister().Get(name)
if err != nil {
return nil, err
}
// ignore the error, skip annotating process if error happened
pods, _ := c.informers.Core().V1().Pods().Lister().Pods("").List(labels.Everything())
// Never mutate original objects!
// Caches are shared across controllers,
// this means that if you mutate your "copy" (actually a reference or shallow copy) of an object,
// you'll mess up other controllers (not just your own).
// Also, if the mutated field is a map,
// a "concurrent map (read &) write" panic might occur,
// causing the ks-apiserver to crash.
// Refer:
// https://github.com/kubesphere/kubesphere/issues/4357
// https://github.com/kubesphere/kubesphere/issues/3469
// https://github.com/kubesphere/kubesphere/pull/4599
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-api-machinery/controllers.md
node = node.DeepCopy()
c.annotateNode(node, pods)
return node, nil
node := &corev1.Node{}
return node, c.cache.Get(context.Background(), types.NamespacedName{Name: name}, node)
}
func (c *nodesGetter) List(_ string, q *query.Query) (*api.ListResult, error) {
nodes, err := c.informers.Core().V1().Nodes().Lister().List(q.Selector())
if err != nil {
nodes := &corev1.NodeList{}
if err := c.cache.List(context.Background(), nodes,
client.MatchingLabelsSelector{Selector: q.Selector()}); err != nil {
return nil, err
}
var filtered []*v1.Node
for _, object := range nodes {
selected := true
for field, value := range q.Filters {
if !c.filter(object, query.Filter{Field: field, Value: value}) {
selected = false
break
}
}
if selected {
filtered = append(filtered, object)
}
var result []runtime.Object
for _, item := range nodes.Items {
result = append(result, item.DeepCopy())
}
// sort by sortBy field
sort.Slice(filtered, func(i, j int) bool {
if !q.Ascending {
return c.compare(filtered[i], filtered[j], q.SortBy)
}
return !c.compare(filtered[i], filtered[j], q.SortBy)
})
total := len(filtered)
if q.Pagination == nil {
q.Pagination = query.NoPagination
}
start, end := q.Pagination.GetValidPagination(total)
selectedNodes := filtered[start:end]
// ignore the error, skip annotating process if error happened
pods, _ := c.informers.Core().V1().Pods().Lister().Pods("").List(labels.Everything())
var nonTerminatedPodsList []*v1.Pod
for _, pod := range pods {
if pod.Status.Phase != v1.PodSucceeded && pod.Status.Phase != v1.PodFailed {
nonTerminatedPodsList = append(nonTerminatedPodsList, pod)
}
}
var result = make([]interface{}, 0)
for _, node := range selectedNodes {
node = node.DeepCopy()
c.annotateNode(node, nonTerminatedPodsList)
result = append(result, node)
}
return &api.ListResult{
TotalItems: total,
Items: result,
}, nil
return v1alpha3.DefaultList(result, q, c.compare, c.filter), nil
}
func (c *nodesGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftNode, ok := left.(*v1.Node)
leftNode, ok := left.(*corev1.Node)
if !ok {
return false
}
rightNode, ok := right.(*v1.Node)
rightNode, ok := right.(*corev1.Node)
if !ok {
return false
}
@@ -159,7 +77,7 @@ func (c *nodesGetter) compare(left runtime.Object, right runtime.Object, field q
}
func (c *nodesGetter) filter(object runtime.Object, filter query.Filter) bool {
node, ok := object.(*v1.Node)
node, ok := object.(*corev1.Node)
if !ok {
return false
}
@@ -167,80 +85,10 @@ func (c *nodesGetter) filter(object runtime.Object, filter query.Filter) bool {
case query.FieldStatus:
return getNodeStatus(node) == string(filter.Value)
}
return v1alpha3.DefaultObjectMetaFilter(node.ObjectMeta, filter)
}
// annotateNode adds cpu/memory requests usage data to node's annotations
// this operation mutates the *v1.Node passed in
// so DO A DEEPCOPY before calling
func (c *nodesGetter) annotateNode(node *v1.Node, pods []*v1.Pod) {
if node.Annotations == nil {
node.Annotations = make(map[string]string)
}
if len(pods) == 0 {
return
}
var nodePods []*v1.Pod
for _, pod := range pods {
if pod.Spec.NodeName == node.Name {
nodePods = append(nodePods, pod)
}
}
reqs, limits := c.getPodsTotalRequestAndLimits(nodePods)
cpuReqs, cpuLimits, memoryReqs, memoryLimits := reqs[v1.ResourceCPU], limits[v1.ResourceCPU], reqs[v1.ResourceMemory], limits[v1.ResourceMemory]
node.Annotations[nodeCPURequests] = cpuReqs.String()
node.Annotations[nodeCPULimits] = cpuLimits.String()
node.Annotations[nodeMemoryRequests] = memoryReqs.String()
node.Annotations[nodeMemoryLimits] = memoryLimits.String()
fractionCpuReqs, fractionCpuLimits := float64(0), float64(0)
allocatable := node.Status.Allocatable
if allocatable.Cpu().MilliValue() != 0 {
fractionCpuReqs = float64(cpuReqs.MilliValue()) / float64(allocatable.Cpu().MilliValue()) * 100
fractionCpuLimits = float64(cpuLimits.MilliValue()) / float64(allocatable.Cpu().MilliValue()) * 100
}
fractionMemoryReqs, fractionMemoryLimits := float64(0), float64(0)
if allocatable.Memory().Value() != 0 {
fractionMemoryReqs = float64(memoryReqs.Value()) / float64(allocatable.Memory().Value()) * 100
fractionMemoryLimits = float64(memoryLimits.Value()) / float64(allocatable.Memory().Value()) * 100
}
node.Annotations[nodeCPURequestsFraction] = fmt.Sprintf("%d%%", int(fractionCpuReqs))
node.Annotations[nodeCPULimitsFraction] = fmt.Sprintf("%d%%", int(fractionCpuLimits))
node.Annotations[nodeMemoryRequestsFraction] = fmt.Sprintf("%d%%", int(fractionMemoryReqs))
node.Annotations[nodeMemoryLimitsFraction] = fmt.Sprintf("%d%%", int(fractionMemoryLimits))
}
func (c *nodesGetter) getPodsTotalRequestAndLimits(pods []*v1.Pod) (reqs map[v1.ResourceName]resource.Quantity, limits map[v1.ResourceName]resource.Quantity) {
reqs, limits = map[v1.ResourceName]resource.Quantity{}, map[v1.ResourceName]resource.Quantity{}
for _, pod := range pods {
podReqs, podLimits := resourceheper.PodRequestsAndLimits(pod)
for podReqName, podReqValue := range podReqs {
if value, ok := reqs[podReqName]; !ok {
reqs[podReqName] = podReqValue.DeepCopy()
} else {
value.Add(podReqValue)
reqs[podReqName] = value
}
}
for podLimitName, podLimitValue := range podLimits {
if value, ok := limits[podLimitName]; !ok {
limits[podLimitName] = podLimitValue.DeepCopy()
} else {
value.Add(podLimitValue)
limits[podLimitName] = value
}
}
}
return
}
func getNodeStatus(node *v1.Node) string {
func getNodeStatus(node *corev1.Node) string {
if node.Spec.Unschedulable {
return statusUnschedulable
}
@@ -253,17 +101,17 @@ func getNodeStatus(node *v1.Node) string {
return statusRunning
}
var expectedConditions = map[v1.NodeConditionType]v1.ConditionStatus{
v1.NodeMemoryPressure: v1.ConditionFalse,
v1.NodeDiskPressure: v1.ConditionFalse,
v1.NodePIDPressure: v1.ConditionFalse,
v1.NodeNetworkUnavailable: v1.ConditionFalse,
nodeConfigOK: v1.ConditionTrue,
nodeKubeletReady: v1.ConditionTrue,
v1.NodeReady: v1.ConditionTrue,
var expectedConditions = map[corev1.NodeConditionType]corev1.ConditionStatus{
corev1.NodeMemoryPressure: corev1.ConditionFalse,
corev1.NodeDiskPressure: corev1.ConditionFalse,
corev1.NodePIDPressure: corev1.ConditionFalse,
corev1.NodeNetworkUnavailable: corev1.ConditionFalse,
nodeConfigOK: corev1.ConditionTrue,
nodeKubeletReady: corev1.ConditionTrue,
corev1.NodeReady: corev1.ConditionTrue,
}
func isUnhealthyStatus(condition v1.NodeCondition) bool {
func isUnhealthyStatus(condition corev1.NodeCondition) bool {
expectedStatus := expectedConditions[condition.Type]
if expectedStatus != "" && condition.Status != expectedStatus {
return true

View File

@@ -1,283 +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 node
import (
"strconv"
"testing"
"github.com/google/go-cmp/cmp"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
// mergeResourceLists will merge resoure lists. When two lists have the same resourece, the value from
// the last list will be present in the result
func mergeResourceLists(resourceLists ...corev1.ResourceList) corev1.ResourceList {
result := corev1.ResourceList{}
for _, rl := range resourceLists {
for resource, quantity := range rl {
result[resource] = quantity
}
}
return result
}
func getResourceList(cpu, memory string) corev1.ResourceList {
res := corev1.ResourceList{}
if cpu != "" {
res[corev1.ResourceCPU] = resource.MustParse(cpu)
}
if memory != "" {
res[corev1.ResourceMemory] = resource.MustParse(memory)
}
return res
}
var nodeAllocatable = mergeResourceLists(getResourceList("4", "12Gi"))
var node = &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
Status: corev1.NodeStatus{
Allocatable: nodeAllocatable,
},
}
var pods = []*corev1.Pod{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "foo",
Name: "pod-with-resources",
},
TypeMeta: metav1.TypeMeta{
Kind: "Pod",
},
Spec: corev1.PodSpec{
NodeName: node.Name,
Containers: []corev1.Container{
{
Name: "cpu-mem",
Image: "image:latest",
Resources: corev1.ResourceRequirements{
Requests: getResourceList("1", "1Gi"),
Limits: getResourceList("2", "2Gi"),
},
},
},
},
Status: corev1.PodStatus{
Phase: corev1.PodRunning,
},
},
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "foo2",
Name: "pod-with-resources",
},
TypeMeta: metav1.TypeMeta{
Kind: "Pod",
},
Spec: corev1.PodSpec{
NodeName: node.Name,
Containers: []corev1.Container{
{
Name: "cpu-mem",
Image: "image:latest",
Resources: corev1.ResourceRequirements{
Requests: getResourceList("1", "1Gi"),
Limits: getResourceList("2", "2Gi"),
},
},
},
},
Status: corev1.PodStatus{
Phase: corev1.PodRunning,
},
},
}
var expectedAnnotations = map[string]string{
nodeCPURequests: "2",
nodeCPULimits: "4",
nodeCPURequestsFraction: "50%",
nodeCPULimitsFraction: "100%",
nodeMemoryRequests: "2Gi",
nodeMemoryLimits: "4Gi",
nodeMemoryRequestsFraction: "16%",
nodeMemoryLimitsFraction: "33%",
}
func TestNodesGetterGet(t *testing.T) {
fake := fake.NewSimpleClientset(node, pods[0], pods[1])
informer := informers.NewSharedInformerFactory(fake, 0)
informer.Core().V1().Nodes().Informer().GetIndexer().Add(node)
for _, pod := range pods {
informer.Core().V1().Pods().Informer().GetIndexer().Add(pod)
}
nodeGetter := New(informer)
got, err := nodeGetter.Get("", node.Name)
if err != nil {
t.Fatal(err)
}
nodeGot := got.(*corev1.Node)
if diff := cmp.Diff(nodeGot.Annotations, expectedAnnotations); len(diff) != 0 {
t.Errorf("%T, diff(-got, +expected), %v", expectedAnnotations, nodeGot.Annotations)
}
}
func TestListNodes(t *testing.T) {
tests := []struct {
query *query.Query
expected *api.ListResult
}{
{
&query.Query{
Pagination: &query.Pagination{
Limit: 1,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{query.FieldName: query.Value(node2.Name)},
},
&api.ListResult{
Items: []interface{}{
node2Expected,
},
TotalItems: 1,
},
},
{
&query.Query{
Pagination: &query.Pagination{
Limit: 1,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{query.FieldStatus: query.Value(statusUnschedulable)},
},
&api.ListResult{
Items: []interface{}{
node1Expected,
},
TotalItems: 1,
},
},
{
&query.Query{
Pagination: &query.Pagination{
Limit: 1,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{query.FieldStatus: query.Value(statusRunning)},
},
&api.ListResult{
Items: []interface{}{
node2Expected,
},
TotalItems: 1,
},
},
}
getter := prepare()
for index, test := range tests {
t.Run(strconv.Itoa(index), func(t *testing.T) {
got, err := getter.List("", test.query)
if err != nil {
t.Error(err)
}
if diff := cmp.Diff(got, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
}
})
}
}
var (
node1 = &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node1",
},
Spec: corev1.NodeSpec{
Unschedulable: true,
},
}
node1Expected = &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node1",
Annotations: map[string]string{},
},
Spec: corev1.NodeSpec{
Unschedulable: true,
},
}
node2 = &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node2",
},
Spec: corev1.NodeSpec{
Unschedulable: false,
},
}
node2Expected = &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node2",
Annotations: map[string]string{},
},
Spec: corev1.NodeSpec{
Unschedulable: false,
},
}
nodes = []*corev1.Node{node1, node2}
)
func prepare() v1alpha3.Interface {
fake := fake.NewSimpleClientset(node1, node2)
informer := informers.NewSharedInformerFactory(fake, 0)
for _, node := range nodes {
informer.Core().V1().Nodes().Informer().GetIndexer().Add(node)
}
return New(informer)
}

View File

@@ -1,192 +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 notification
import (
"strings"
"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"
)
type notificationmanagerGetter struct {
ksInformer ksinformers.SharedInformerFactory
}
func NewNotificationManagerGetter(informer ksinformers.SharedInformerFactory) v1alpha3.Interface {
return &notificationmanagerGetter{ksInformer: informer}
}
func (g *notificationmanagerGetter) Get(_, name string) (runtime.Object, error) {
return g.ksInformer.Notification().V2beta2().NotificationManagers().Lister().Get(name)
}
func (g *notificationmanagerGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
objs, err := g.ksInformer.Notification().V2beta2().NotificationManagers().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 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().V2beta2().Configs().Lister().Get(name)
}
func (g *configGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
objs, err := g.ksInformer.Notification().V2beta2().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().V2beta2().Receivers().Lister().Get(name)
}
func (g *receiverGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
objs, err := g.ksInformer.Notification().V2beta2().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
}
type routerGetter struct {
ksInformer ksinformers.SharedInformerFactory
}
func NewNotificationRouterGetter(informer ksinformers.SharedInformerFactory) v1alpha3.Interface {
return &routerGetter{ksInformer: informer}
}
func (g *routerGetter) Get(_, name string) (runtime.Object, error) {
return g.ksInformer.Notification().V2beta2().Routers().Lister().Get(name)
}
func (g *routerGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
objs, err := g.ksInformer.Notification().V2beta2().Routers().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 silenceGetter struct {
ksInformer ksinformers.SharedInformerFactory
}
func NewNotificationSilenceGetter(informer ksinformers.SharedInformerFactory) v1alpha3.Interface {
return &silenceGetter{ksInformer: informer}
}
func (g *silenceGetter) Get(_, name string) (runtime.Object, error) {
return g.ksInformer.Notification().V2beta2().Silences().Lister().Get(name)
}
func (g *silenceGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
objs, err := g.ksInformer.Notification().V2beta2().Silences().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

@@ -1,158 +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 notification
import (
"math/rand"
"sort"
"testing"
"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/api/notification/v2beta2"
"kubesphere.io/kubesphere/pkg/api"
"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"
)
const (
Prefix = "foo"
LengthMin = 3
LengthMax = 10
)
func TestListObjects(t *testing.T) {
tests := []struct {
description string
key string
}{
{
"test name filter",
v2beta2.ResourcesPluralConfig,
},
{
"test name filter",
v2beta2.ResourcesPluralReceiver,
},
{
"test name filter",
v2beta2.ResourcesPluralRouter,
},
{
"test name filter",
v2beta2.ResourcesPluralSilence,
},
}
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 v2beta2.ResourcesPluralConfig:
indexer = informer.Notification().V2beta2().Configs().Informer().GetIndexer()
getter = NewNotificationConfigGetter
obj = &v2beta2.Config{}
case v2beta2.ResourcesPluralReceiver:
indexer = informer.Notification().V2beta2().Receivers().Informer().GetIndexer()
getter = NewNotificationReceiverGetter
obj = &v2beta2.Receiver{}
case v2beta2.ResourcesPluralRouter:
indexer = informer.Notification().V2beta2().Routers().Informer().GetIndexer()
getter = NewNotificationRouterGetter
obj = &v2beta2.Router{}
case v2beta2.ResourcesPluralSilence:
indexer = informer.Notification().V2beta2().Silences().Informer().GetIndexer()
getter = NewNotificationSilenceGetter
obj = &v2beta2.Silence{}
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

@@ -1,14 +0,0 @@
approvers:
- zheng1
- wansir
- zryfish
reviewers:
- zheng1
- wansir
- zryfish
- xyz-li
labels:
- area/api
- area/app-management

View File

@@ -1,102 +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 (
"strings"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
"kubesphere.io/api/application/v1alpha1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type helmApplicationsGetter struct {
informers externalversions.SharedInformerFactory
}
func New(informers externalversions.SharedInformerFactory) v1alpha3.Interface {
return &helmApplicationsGetter{
informers: informers,
}
}
func (r *helmApplicationsGetter) Get(_, name string) (runtime.Object, error) {
app, err := r.informers.Application().V1alpha1().HelmApplications().Lister().Get(name)
if err != nil {
klog.Error(err)
return nil, err
}
return app, nil
}
func (r *helmApplicationsGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
var apps []*v1alpha1.HelmApplication
var err error
apps, err = r.informers.Application().V1alpha1().HelmApplications().Lister().List(query.Selector())
if err != nil {
klog.Error(err)
return nil, err
}
var result []runtime.Object
for i := range apps {
result = append(result, apps[i])
}
return v1alpha3.DefaultList(result, query, r.compare, r.filter), nil
}
func (r *helmApplicationsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftApp, ok := left.(*v1alpha1.HelmApplication)
if !ok {
return false
}
rightApp, ok := right.(*v1alpha1.HelmApplication)
if !ok {
return false
}
switch field {
case query.FieldName:
return strings.Compare(leftApp.Spec.Name, rightApp.Spec.Name) > 0
default:
return v1alpha3.DefaultObjectMetaCompare(leftApp.ObjectMeta, rightApp.ObjectMeta, field)
}
}
func (r *helmApplicationsGetter) filter(object runtime.Object, filter query.Filter) bool {
application, ok := object.(*v1alpha1.HelmApplication)
if !ok {
return false
}
switch filter.Field {
case query.FieldName:
return strings.Contains(application.Spec.Name, string(filter.Value))
case query.FieldStatus:
return strings.Contains(application.Status.State, string(filter.Value))
default:
return v1alpha3.DefaultObjectMetaFilter(application.ObjectMeta, filter)
}
}

View File

@@ -1,102 +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 applicationversion
import (
"strings"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
"kubesphere.io/api/application/v1alpha1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type applicationVersionsGetter struct {
informers externalversions.SharedInformerFactory
}
func New(informers externalversions.SharedInformerFactory) v1alpha3.Interface {
return &applicationVersionsGetter{
informers: informers,
}
}
func (r *applicationVersionsGetter) Get(_, name string) (runtime.Object, error) {
app, err := r.informers.Application().V1alpha1().HelmApplicationVersions().Lister().Get(name)
if err != nil {
klog.Error(err)
return nil, err
}
return app, nil
}
func (r *applicationVersionsGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
var apps []*v1alpha1.HelmApplicationVersion
var err error
apps, err = r.informers.Application().V1alpha1().HelmApplicationVersions().Lister().List(query.Selector())
if err != nil {
klog.Error(err)
return nil, err
}
var result []runtime.Object
for i := range apps {
result = append(result, apps[i])
}
return v1alpha3.DefaultList(result, query, r.compare, r.filter), nil
}
func (r *applicationVersionsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftAppVer, ok := left.(*v1alpha1.HelmApplicationVersion)
if !ok {
return false
}
rightAppVer, ok := right.(*v1alpha1.HelmApplicationVersion)
if !ok {
return false
}
switch field {
case query.FieldName:
return strings.Compare(leftAppVer.Spec.Name, rightAppVer.Spec.Name) > 0
default:
return v1alpha3.DefaultObjectMetaCompare(leftAppVer.ObjectMeta, rightAppVer.ObjectMeta, field)
}
}
func (r *applicationVersionsGetter) filter(object runtime.Object, filter query.Filter) bool {
appVer, ok := object.(*v1alpha1.HelmApplicationVersion)
if !ok {
return false
}
switch filter.Field {
case query.FieldName:
return strings.Contains(appVer.Spec.Name, string(filter.Value))
case query.FieldStatus:
return strings.Contains(appVer.Status.State, string(filter.Value))
default:
return v1alpha3.DefaultObjectMetaFilter(appVer.ObjectMeta, filter)
}
}

View File

@@ -1,100 +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 category
import (
"strings"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
"kubesphere.io/api/application/v1alpha1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type helmCategoriesGetter struct {
informers externalversions.SharedInformerFactory
}
func New(informers externalversions.SharedInformerFactory) v1alpha3.Interface {
return &helmCategoriesGetter{
informers: informers,
}
}
func (r *helmCategoriesGetter) Get(_, name string) (runtime.Object, error) {
app, err := r.informers.Application().V1alpha1().HelmCategories().Lister().Get(name)
if err != nil {
klog.Error(err)
return nil, err
}
return app, nil
}
func (r *helmCategoriesGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
var ctg []*v1alpha1.HelmCategory
var err error
ctg, err = r.informers.Application().V1alpha1().HelmCategories().Lister().List(query.Selector())
if err != nil {
klog.Error(err)
return nil, err
}
var result []runtime.Object
for i := range ctg {
result = append(result, ctg[i])
}
return v1alpha3.DefaultList(result, query, r.compare, r.filter), nil
}
func (r *helmCategoriesGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
ctg1, ok := left.(*v1alpha1.HelmCategory)
if !ok {
return false
}
ctg2, ok := right.(*v1alpha1.HelmCategory)
if !ok {
return false
}
switch field {
case query.FieldName:
return strings.Compare(ctg1.Spec.Name, ctg2.Spec.Name) > 0
default:
return v1alpha3.DefaultObjectMetaCompare(ctg1.ObjectMeta, ctg2.ObjectMeta, field)
}
}
func (r *helmCategoriesGetter) filter(object runtime.Object, filter query.Filter) bool {
application, ok := object.(*v1alpha1.HelmCategory)
if !ok {
return false
}
switch filter.Field {
case query.FieldName:
return strings.Contains(application.Spec.Name, string(filter.Value))
default:
return v1alpha3.DefaultObjectMetaFilter(application.ObjectMeta, filter)
}
}

View File

@@ -1,102 +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 helmrelease
import (
"strings"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
"kubesphere.io/api/application/v1alpha1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type helmReleasesGetter struct {
informers externalversions.SharedInformerFactory
}
func New(informers externalversions.SharedInformerFactory) v1alpha3.Interface {
return &helmReleasesGetter{
informers: informers,
}
}
func (r *helmReleasesGetter) Get(_, name string) (runtime.Object, error) {
app, err := r.informers.Application().V1alpha1().HelmReleases().Lister().Get(name)
if err != nil {
klog.Error(err)
return nil, err
}
return app, nil
}
func (r *helmReleasesGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
var rls []*v1alpha1.HelmRelease
var err error
rls, err = r.informers.Application().V1alpha1().HelmReleases().Lister().List(query.Selector())
if err != nil {
klog.Error(err)
return nil, err
}
var result []runtime.Object
for i := range rls {
result = append(result, rls[i])
}
return v1alpha3.DefaultList(result, query, r.compare, r.filter), nil
}
func (r *helmReleasesGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftRls, ok := left.(*v1alpha1.HelmRelease)
if !ok {
return false
}
rightRls, ok := right.(*v1alpha1.HelmRelease)
if !ok {
return false
}
switch field {
case query.FieldName:
return strings.Compare(leftRls.Spec.Name, rightRls.Spec.Name) > 0
default:
return v1alpha3.DefaultObjectMetaCompare(leftRls.ObjectMeta, rightRls.ObjectMeta, field)
}
}
func (r *helmReleasesGetter) filter(object runtime.Object, filter query.Filter) bool {
rls, ok := object.(*v1alpha1.HelmRelease)
if !ok {
return false
}
switch filter.Field {
case query.FieldName:
return strings.Contains(rls.Spec.Name, string(filter.Value))
case query.FieldStatus:
return strings.Contains(rls.Status.State, string(filter.Value))
default:
return v1alpha3.DefaultObjectMetaFilter(rls.ObjectMeta, filter)
}
}

View File

@@ -1,94 +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 repo
import (
"strings"
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/api/application/v1alpha1"
"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"
)
type reposGetter struct {
ksInformer ksinformers.SharedInformerFactory
}
func New(ksinformer ksinformers.SharedInformerFactory) v1alpha3.Interface {
return &reposGetter{ksInformer: ksinformer}
}
func (d *reposGetter) Get(_, name string) (runtime.Object, error) {
return d.ksInformer.Application().V1alpha1().HelmRepos().Lister().Get(name)
}
func (d *reposGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
var repos []*v1alpha1.HelmRepo
var err error
repos, err = d.ksInformer.Application().V1alpha1().HelmRepos().Lister().List(query.Selector())
if err != nil {
return nil, err
}
result := make([]runtime.Object, 0, len(repos))
for _, user := range repos {
result = append(result, user)
}
return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil
}
func (d *reposGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
repo1, ok := left.(*v1alpha1.HelmRepo)
if !ok {
return false
}
repo2, ok := right.(*v1alpha1.HelmRepo)
if !ok {
return false
}
switch field {
case query.FieldName:
return strings.Compare(repo1.Spec.Name, repo2.Spec.Name) > 0
default:
return v1alpha3.DefaultObjectMetaCompare(repo1.ObjectMeta, repo2.ObjectMeta, field)
}
}
func (d *reposGetter) filter(object runtime.Object, filter query.Filter) bool {
repo, ok := object.(*v1alpha1.HelmRepo)
if !ok {
return false
}
switch filter.Field {
case query.FieldName:
return strings.Contains(repo.Spec.Name, string(filter.Value))
default:
return v1alpha3.DefaultObjectMetaFilter(repo.ObjectMeta, filter)
}
}

View File

@@ -1,27 +1,20 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package persistentvolume
import (
"context"
"strings"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
@@ -33,26 +26,27 @@ const (
)
type persistentVolumeGetter struct {
informers informers.SharedInformerFactory
cache runtimeclient.Reader
}
func New(informer informers.SharedInformerFactory) v1alpha3.Interface {
return &persistentVolumeGetter{informers: informer}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &persistentVolumeGetter{cache: cache}
}
func (p *persistentVolumeGetter) Get(namespace, name string) (runtime.Object, error) {
pv, err := p.informers.Core().V1().PersistentVolumes().Lister().Get(name)
return pv, err
func (p *persistentVolumeGetter) Get(_, name string) (runtime.Object, error) {
pv := &corev1.PersistentVolume{}
return pv, p.cache.Get(context.Background(), types.NamespacedName{Name: name}, pv)
}
func (p *persistentVolumeGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
all, err := p.informers.Core().V1().PersistentVolumes().Lister().List(query.Selector())
if err != nil {
persistentVolumes := &corev1.PersistentVolumeList{}
if err := p.cache.List(context.Background(), persistentVolumes, client.InNamespace(namespace),
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
for _, pv := range all {
result = append(result, pv)
for _, item := range persistentVolumes.Items {
result = append(result, item.DeepCopy())
}
return v1alpha3.DefaultList(result, query, p.compare, p.filter), nil
}

View File

@@ -1,140 +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 persistentvolume
import (
"testing"
"github.com/google/go-cmp/cmp"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
var (
testStorageClassName = "test-csi"
)
func TestListPods(t *testing.T) {
tests := []struct {
description string
namespace string
query *query.Query
expected *api.ListResult
expectedErr error
}{
{
"test name filter",
"",
&query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{},
},
&api.ListResult{
Items: []interface{}{pv3, pv2, pv1},
TotalItems: len(persistentVolumes),
},
nil,
},
{
"test status filter",
"",
&query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{
query.FieldStatus: query.Value(pv1.Status.Phase),
},
},
&api.ListResult{
Items: []interface{}{pv1},
TotalItems: 1,
},
nil,
},
}
getter := prepare()
for _, test := range tests {
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, test.expected); diff != "" {
t.Errorf("[%s] %T differ (-got, +want): %s", test.description, test.expected, diff)
}
}
}
var (
pv1 = &corev1.PersistentVolume{
TypeMeta: metav1.TypeMeta{},
ObjectMeta: metav1.ObjectMeta{
Name: "pv-1",
},
Status: corev1.PersistentVolumeStatus{
Phase: "bound",
},
}
pv2 = &corev1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{
Name: "pv-2",
},
Status: corev1.PersistentVolumeStatus{
Phase: "available",
},
Spec: corev1.PersistentVolumeSpec{
StorageClassName: testStorageClassName,
},
}
pv3 = &corev1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{
Name: "pvc-3",
Namespace: "default",
},
}
persistentVolumes = []interface{}{pv1, pv2, pv3}
)
func prepare() v1alpha3.Interface {
client := fake.NewSimpleClientset()
informer := informers.NewSharedInformerFactory(client, 0)
for _, pv := range persistentVolumes {
_ = informer.Core().V1().PersistentVolumes().Informer().GetIndexer().Add(pv)
}
return New(informer)
}

View File

@@ -1,30 +1,20 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package persistentvolumeclaim
import (
"strconv"
"context"
"strings"
snapshotinformers "github.com/kubernetes-csi/external-snapshotter/client/v4/informers/externalversions"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
@@ -32,113 +22,67 @@ import (
)
const (
storageClassName = "storageClassName"
storageClassName = "storageClassName"
annotationInUse = "kubesphere.io/in-use"
annotationAllowSnapshot = "kubesphere.io/allow-snapshot"
annotationStorageProvisioner = "volume.beta.kubernetes.io/storage-provisioner"
)
type persistentVolumeClaimGetter struct {
informers informers.SharedInformerFactory
snapshotInformers snapshotinformers.SharedInformerFactory
cache runtimeclient.Reader
}
func New(informer informers.SharedInformerFactory, snapshotInformer snapshotinformers.SharedInformerFactory) v1alpha3.Interface {
return &persistentVolumeClaimGetter{informers: informer, snapshotInformers: snapshotInformer}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &persistentVolumeClaimGetter{cache: cache}
}
func (p *persistentVolumeClaimGetter) Get(namespace, name string) (runtime.Object, error) {
pvc, err := p.informers.Core().V1().PersistentVolumeClaims().Lister().PersistentVolumeClaims(namespace).Get(name)
if err != nil {
return pvc, err
}
// we should never mutate the shared objects from informers
pvc = pvc.DeepCopy()
p.annotatePVC(pvc)
return pvc, nil
pvc := &corev1.PersistentVolumeClaim{}
return pvc, p.cache.Get(context.Background(), types.NamespacedName{Namespace: namespace, Name: name}, pvc)
}
func (p *persistentVolumeClaimGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
all, err := p.informers.Core().V1().PersistentVolumeClaims().Lister().PersistentVolumeClaims(namespace).List(query.Selector())
if err != nil {
persistentVolumeClaims := &corev1.PersistentVolumeClaimList{}
if err := p.cache.List(context.Background(), persistentVolumeClaims, client.InNamespace(namespace),
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
for _, pvc := range all {
pvc = pvc.DeepCopy()
p.annotatePVC(pvc)
result = append(result, pvc)
for _, item := range persistentVolumeClaims.Items {
result = append(result, item.DeepCopy())
}
return v1alpha3.DefaultList(result, query, p.compare, p.filter), nil
}
func (p *persistentVolumeClaimGetter) compare(left, right runtime.Object, field query.Field) bool {
leftSnapshot, ok := left.(*v1.PersistentVolumeClaim)
leftPVC, ok := left.(*corev1.PersistentVolumeClaim)
if !ok {
return false
}
rightSnapshot, ok := right.(*v1.PersistentVolumeClaim)
rightPVC, ok := right.(*corev1.PersistentVolumeClaim)
if !ok {
return false
}
return v1alpha3.DefaultObjectMetaCompare(leftSnapshot.ObjectMeta, rightSnapshot.ObjectMeta, field)
return v1alpha3.DefaultObjectMetaCompare(leftPVC.ObjectMeta, rightPVC.ObjectMeta, field)
}
func (p *persistentVolumeClaimGetter) filter(object runtime.Object, filter query.Filter) bool {
pvc, ok := object.(*v1.PersistentVolumeClaim)
pvc, ok := object.(*corev1.PersistentVolumeClaim)
if !ok {
return false
}
switch filter.Field {
case query.FieldStatus:
return strings.EqualFold(string(pvc.Status.Phase), string(filter.Value))
statuses := strings.Split(string(filter.Value), "|")
for _, status := range statuses {
if !strings.EqualFold(string(pvc.Status.Phase), status) {
return false
}
}
return true
case storageClassName:
return pvc.Spec.StorageClassName != nil && *pvc.Spec.StorageClassName == string(filter.Value)
default:
return v1alpha3.DefaultObjectMetaFilter(pvc.ObjectMeta, filter)
}
}
func (p *persistentVolumeClaimGetter) annotatePVC(pvc *v1.PersistentVolumeClaim) {
inUse := p.countPods(pvc.Name, pvc.Namespace)
isSnapshotAllow := p.isSnapshotAllowed(pvc.GetAnnotations()[annotationStorageProvisioner])
if pvc.Annotations == nil {
pvc.Annotations = make(map[string]string)
}
pvc.Annotations[annotationInUse] = strconv.FormatBool(inUse)
pvc.Annotations[annotationAllowSnapshot] = strconv.FormatBool(isSnapshotAllow)
}
func (p *persistentVolumeClaimGetter) countPods(name, namespace string) bool {
pods, err := p.informers.Core().V1().Pods().Lister().Pods(namespace).List(labels.Everything())
if err != nil {
return false
}
for _, pod := range pods {
for _, pvc := range pod.Spec.Volumes {
if pvc.PersistentVolumeClaim != nil && pvc.PersistentVolumeClaim.ClaimName == name {
return true
}
}
}
return false
}
func (p *persistentVolumeClaimGetter) isSnapshotAllowed(provisioner string) bool {
if len(provisioner) == 0 {
return false
}
volumeSnapshotClasses, err := p.snapshotInformers.Snapshot().V1().VolumeSnapshotClasses().Lister().List(labels.Everything())
if err != nil {
return false
}
for _, volumeSnapshotClass := range volumeSnapshotClasses {
if volumeSnapshotClass.Driver == provisioner {
return true
}
}
return false
}

View File

@@ -1,267 +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 persistentvolumeclaim
import (
"testing"
"github.com/google/go-cmp/cmp"
snapshot "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
snapshotefakeclient "github.com/kubernetes-csi/external-snapshotter/client/v4/clientset/versioned/fake"
snapshotinformers "github.com/kubernetes-csi/external-snapshotter/client/v4/informers/externalversions"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
var (
testStorageClassName = "test-csi"
)
func TestListPVCs(t *testing.T) {
tests := []struct {
description string
namespace string
query *query.Query
expected *api.ListResult
expectedErr error
}{
{
"test name filter",
"default",
&query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{query.FieldNamespace: query.Value("default")},
},
&api.ListResult{
Items: []interface{}{pvc3Expected, pvc2Expected, pvc1Expected},
TotalItems: len(persistentVolumeClaims),
},
nil,
},
{
"test status filter",
"default",
&query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{
query.FieldNamespace: query.Value("default"),
query.FieldStatus: query.Value(pvc1.Status.Phase),
},
},
&api.ListResult{
Items: []interface{}{pvc1Expected},
TotalItems: 1,
},
nil,
},
{
"test StorageClass filter and allow snapshot",
"default",
&query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{
query.FieldNamespace: query.Value("default"),
query.Field(storageClassName): query.Value(*pvc2.Spec.StorageClassName),
},
},
&api.ListResult{
Items: []interface{}{pvc2Expected},
TotalItems: 1,
},
nil,
},
{
"test pvc in use",
"default",
&query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{
query.FieldNamespace: query.Value("default"),
query.FieldName: query.Value(pvc3.Name),
},
},
&api.ListResult{
Items: []interface{}{pvc3Expected},
TotalItems: 1,
},
nil,
},
}
getter := prepare()
for _, test := range tests {
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, test.expected); diff != "" {
t.Errorf("[%s] %T differ (-got, +want): %s", test.description, test.expected, diff)
}
}
}
var (
pvc1 = &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "pvc-1",
Namespace: "default",
},
Status: corev1.PersistentVolumeClaimStatus{
Phase: corev1.ClaimPending,
},
}
pvc1Expected = &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "pvc-1",
Namespace: "default",
Annotations: map[string]string{
annotationInUse: "false",
annotationAllowSnapshot: "false",
},
},
Status: corev1.PersistentVolumeClaimStatus{
Phase: corev1.ClaimPending,
},
}
pvc2 = &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "pvc-2",
Namespace: "default",
Annotations: map[string]string{
annotationStorageProvisioner: testStorageClassName,
},
},
Spec: corev1.PersistentVolumeClaimSpec{
StorageClassName: &testStorageClassName,
},
}
pvc2Expected = &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "pvc-2",
Namespace: "default",
Annotations: map[string]string{
annotationInUse: "false",
annotationAllowSnapshot: "true",
annotationStorageProvisioner: testStorageClassName,
},
},
Spec: corev1.PersistentVolumeClaimSpec{
StorageClassName: &testStorageClassName,
},
}
pvc3 = &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "pvc-3",
Namespace: "default",
},
}
pvc3Expected = &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "pvc-3",
Namespace: "default",
Annotations: map[string]string{
annotationInUse: "true",
annotationAllowSnapshot: "false",
},
},
}
pod1 = &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod-1",
Namespace: "default",
},
Spec: corev1.PodSpec{
Volumes: []corev1.Volume{
{
Name: "data",
VolumeSource: corev1.VolumeSource{
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
ClaimName: pvc3.Name,
},
},
},
},
},
}
volumeSnapshotClass1 = &snapshot.VolumeSnapshotClass{
ObjectMeta: metav1.ObjectMeta{
Name: "VolumeSnapshotClass-1",
Namespace: "default",
},
Driver: testStorageClassName,
}
persistentVolumeClaims = []interface{}{pvc1, pvc2, pvc3}
pods = []interface{}{pod1}
volumeSnapshotClasses = []interface{}{volumeSnapshotClass1}
)
func prepare() v1alpha3.Interface {
client := fake.NewSimpleClientset()
informer := informers.NewSharedInformerFactory(client, 0)
snapshotClient := snapshotefakeclient.NewSimpleClientset()
snapshotInformers := snapshotinformers.NewSharedInformerFactory(snapshotClient, 0)
for _, pvc := range persistentVolumeClaims {
_ = informer.Core().V1().PersistentVolumeClaims().Informer().GetIndexer().Add(pvc)
}
for _, pod := range pods {
_ = informer.Core().V1().Pods().Informer().GetIndexer().Add(pod)
}
for _, volumeSnapshotClass := range volumeSnapshotClasses {
_ = snapshotInformers.Snapshot().V1().VolumeSnapshotClasses().Informer().GetIndexer().Add(volumeSnapshotClass)
}
return New(informer, snapshotInformers)
}

View File

@@ -1,29 +1,21 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package pod
import (
"context"
"fmt"
"strings"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
@@ -45,34 +37,35 @@ const (
)
type podsGetter struct {
informer informers.SharedInformerFactory
cache runtimeclient.Reader
}
func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface {
return &podsGetter{informer: sharedInformers}
func New(cache runtimeclient.Reader) v1alpha3.Interface {
return &podsGetter{cache: cache}
}
func (p *podsGetter) Get(namespace, name string) (runtime.Object, error) {
return p.informer.Core().V1().Pods().Lister().Pods(namespace).Get(name)
pod := &corev1.Pod{}
if err := p.cache.Get(context.Background(), types.NamespacedName{Namespace: namespace, Name: name}, pod); err != nil {
return nil, err
}
return p.setPodStatus(pod.DeepCopy()), nil
}
func (p *podsGetter) List(namespace string, query *query.Query) (*api.ListResult, error) {
pods, err := p.informer.Core().V1().Pods().Lister().Pods(namespace).List(query.Selector())
if err != nil {
pods := &corev1.PodList{}
if err := p.cache.List(context.Background(), pods, client.InNamespace(namespace),
client.MatchingLabelsSelector{Selector: query.Selector()}); err != nil {
return nil, err
}
var result []runtime.Object
for _, pod := range pods {
result = append(result, pod)
for _, item := range pods.Items {
result = append(result, p.setPodStatus(item.DeepCopy()))
}
return v1alpha3.DefaultList(result, query, p.compare, p.filter), nil
}
func (p *podsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
leftPod, ok := left.(*corev1.Pod)
if !ok {
return false
@@ -100,8 +93,7 @@ func (p *podsGetter) filter(object runtime.Object, filter query.Filter) bool {
case fieldServiceName:
return p.podBelongToService(pod, string(filter.Value))
case fieldStatus:
_, statusType := p.getPodStatus(pod)
return statusType == string(filter.Value)
return p.getPodStatus(pod) == string(filter.Value)
case fieldPhase:
return string(pod.Status.Phase) == string(filter.Value)
case fieldPodIP:
@@ -131,8 +123,8 @@ func (p *podsGetter) podBindPVC(item *corev1.Pod, pvcName string) bool {
}
func (p *podsGetter) podBelongToService(item *corev1.Pod, serviceName string) bool {
service, err := p.informer.Core().V1().Services().Lister().Services(item.Namespace).Get(serviceName)
if err != nil {
service := &corev1.Service{}
if err := p.cache.Get(context.Background(), types.NamespacedName{Namespace: item.Namespace, Name: serviceName}, service); err != nil {
return false
}
selector := labels.Set(service.Spec.Selector).AsSelectorPreValidated()
@@ -142,13 +134,18 @@ func (p *podsGetter) podBelongToService(item *corev1.Pod, serviceName string) bo
return true
}
func (p *podsGetter) setPodStatus(pod *corev1.Pod) *corev1.Pod {
pod.Status.Phase = corev1.PodPhase(p.getPodStatus(pod))
return pod
}
// getPodStatus refer to `kubectl get po` result.
// https://github.com/kubernetes/kubernetes/blob/45279654db87f4908911569c07afc42804f0e246/pkg/printers/internalversion/printers.go#L820-920
// podStatusPhase = []string("Pending", "Running","Succeeded","Failed","Unknown")
// podStatusReasons = []string{"Evicted", "NodeAffinity", "NodeLost", "Shutdown", "UnexpectedAdmissionError"}
// containerWaitingReasons = []string{"ContainerCreating", "CrashLoopBackOff", "CreateContainerConfigError", "ErrImagePull", "ImagePullBackOff", "CreateContainerError", "InvalidImageName"}
// containerTerminatedReasons = []string{"OOMKilled", "Completed", "Error", "ContainerCannotRun", "DeadlineExceeded", "Evicted"}
func (p *podsGetter) getPodStatus(pod *corev1.Pod) (string, string) {
func (p *podsGetter) getPodStatus(pod *corev1.Pod) string {
reason := string(pod.Status.Phase)
if pod.Status.Reason != "" {
@@ -251,7 +248,7 @@ func (p *podsGetter) getPodStatus(pod *corev1.Pod) (string, string) {
statusType = statusTypeError
}
}
return reason, statusType
return statusType
}
func hasPodReadyCondition(conditions []corev1.PodCondition) bool {

View File

@@ -1,180 +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 pod
import (
"testing"
"github.com/google/go-cmp/cmp"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
func TestListPods(t *testing.T) {
tests := []struct {
description string
namespace string
query *query.Query
expected *api.ListResult
expectedErr error
}{
{
"test name filter",
"default",
&query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{query.FieldNamespace: query.Value("default")},
},
&api.ListResult{
Items: []interface{}{foo5, foo4, foo3, foo2, foo1},
TotalItems: len(pods),
},
nil,
},
{
"test pvcName filter",
"default",
&query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{
query.FieldNamespace: query.Value("default"),
fieldPVCName: query.Value(foo4.Spec.Volumes[0].PersistentVolumeClaim.ClaimName),
},
},
&api.ListResult{
Items: []interface{}{foo4},
TotalItems: 1,
},
nil,
},
{
"test phase filter",
"default",
&query.Query{
Pagination: &query.Pagination{
Limit: 10,
Offset: 0,
},
SortBy: query.FieldName,
Ascending: false,
Filters: map[query.Field]query.Value{
query.FieldNamespace: query.Value("default"),
fieldPhase: query.Value(corev1.PodRunning),
},
},
&api.ListResult{
Items: []interface{}{foo5},
TotalItems: 1,
},
nil,
},
}
getter := prepare()
for _, test := range tests {
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, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
}
}
}
var (
foo1 = &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "foo1",
Namespace: "default",
},
}
foo2 = &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "foo2",
Namespace: "default",
},
}
foo3 = &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "foo3",
Namespace: "default",
},
}
foo4 = &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "foo4",
Namespace: "default",
},
Spec: corev1.PodSpec{
Volumes: []corev1.Volume{
{
Name: "data",
VolumeSource: corev1.VolumeSource{
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
ClaimName: "pvc-1",
ReadOnly: false,
},
},
},
},
},
}
foo5 = &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "foo5",
Namespace: "default",
},
Status: corev1.PodStatus{
Phase: corev1.PodRunning,
},
}
pods = []interface{}{foo1, foo2, foo3, foo4, foo5}
)
func prepare() v1alpha3.Interface {
client := fake.NewSimpleClientset()
informer := informers.NewSharedInformerFactory(client, 0)
for _, pod := range pods {
_ = informer.Core().V1().Pods().Informer().GetIndexer().Add(pod)
}
return New(informer)
}

View File

@@ -1,82 +1,46 @@
/*
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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package resource
import (
"errors"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/volumesnapshotcontent"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/volumesnapshotclass"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/persistentvolume"
snapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
"github.com/Masterminds/semver/v3"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
monitoringdashboardv1alpha2 "kubesphere.io/monitoring-dashboard/api/v1alpha2"
"sigs.k8s.io/controller-runtime/pkg/cache"
clusterv1alpha1 "kubesphere.io/api/cluster/v1alpha1"
devopsv1alpha3 "kubesphere.io/api/devops/v1alpha3"
iamv1alpha2 "kubesphere.io/api/iam/v1alpha2"
networkv1alpha1 "kubesphere.io/api/network/v1alpha1"
notificationv2beta2 "kubesphere.io/api/notification/v2beta2"
tenantv1alpha1 "kubesphere.io/api/tenant/v1alpha1"
tenantv1alpha2 "kubesphere.io/api/tenant/v1alpha2"
typesv1beta1 "kubesphere.io/api/types/v1beta1"
iamv1beta1 "kubesphere.io/api/iam/v1beta1"
"kubesphere.io/api/tenant/v1beta1"
tenantv1beta1 "kubesphere.io/api/tenant/v1beta1"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/application"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/cluster"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/clusterdashboard"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/clusterrole"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/clusterrolebinding"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/configmap"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/cronjob"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/customresourcedefinition"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/daemonset"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/dashboard"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/deployment"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/devops"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/federatedapplication"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/federatedconfigmap"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/federateddeployment"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/federatedingress"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/federatednamespace"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/federatedpersistentvolumeclaim"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/federatedsecret"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/federatedservice"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/federatedstatefulset"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/globalrole"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/globalrolebinding"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/group"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/groupbinding"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/hpa"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/ingress"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/ippool"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/job"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/label"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/loginrecord"
"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/persistentvolume"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/persistentvolumeclaim"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/pod"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/role"
@@ -86,7 +50,6 @@ import (
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/serviceaccount"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/statefulset"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/user"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/volumesnapshot"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/workspace"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/workspacerole"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/workspacerolebinding"
@@ -95,74 +58,53 @@ import (
var ErrResourceNotSupported = errors.New("resource is not supported")
type ResourceGetter struct {
type Getter struct {
clusterResourceGetters map[schema.GroupVersionResource]v1alpha3.Interface
namespacedResourceGetters map[schema.GroupVersionResource]v1alpha3.Interface
}
func NewResourceGetter(factory informers.InformerFactory, cache cache.Cache) *ResourceGetter {
func NewResourceGetter(cache runtimeclient.Reader, k8sVersion *semver.Version) *Getter {
namespacedResourceGetters := make(map[schema.GroupVersionResource]v1alpha3.Interface)
clusterResourceGetters := make(map[schema.GroupVersionResource]v1alpha3.Interface)
namespacedResourceGetters[schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}] = deployment.New(factory.KubernetesSharedInformerFactory())
namespacedResourceGetters[schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "daemonsets"}] = daemonset.New(factory.KubernetesSharedInformerFactory())
namespacedResourceGetters[schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "statefulsets"}] = statefulset.New(factory.KubernetesSharedInformerFactory())
namespacedResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "services"}] = service.New(factory.KubernetesSharedInformerFactory())
namespacedResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "configmaps"}] = configmap.New(factory.KubernetesSharedInformerFactory())
namespacedResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "secrets"}] = secret.New(factory.KubernetesSharedInformerFactory())
namespacedResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}] = pod.New(factory.KubernetesSharedInformerFactory())
namespacedResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "serviceaccounts"}] = serviceaccount.New(factory.KubernetesSharedInformerFactory())
namespacedResourceGetters[schema.GroupVersionResource{Group: "networking.k8s.io", Version: "v1", Resource: "ingresses"}] = ingress.New(factory.KubernetesSharedInformerFactory())
namespacedResourceGetters[schema.GroupVersionResource{Group: "networking.k8s.io", Version: "v1", Resource: "networkpolicies"}] = networkpolicy.New(factory.KubernetesSharedInformerFactory())
namespacedResourceGetters[schema.GroupVersionResource{Group: "batch", Version: "v1", Resource: "jobs"}] = job.New(factory.KubernetesSharedInformerFactory())
namespacedResourceGetters[schema.GroupVersionResource{Group: "app.k8s.io", Version: "v1beta1", Resource: "applications"}] = application.New(cache)
clusterResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumes"}] = persistentvolume.New(factory.KubernetesSharedInformerFactory())
namespacedResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumeclaims"}] = persistentvolumeclaim.New(factory.KubernetesSharedInformerFactory(), factory.SnapshotSharedInformerFactory())
namespacedResourceGetters[snapshotv1.SchemeGroupVersion.WithResource("volumesnapshots")] = volumesnapshot.New(factory.SnapshotSharedInformerFactory())
clusterResourceGetters[snapshotv1.SchemeGroupVersion.WithResource("volumesnapshotclasses")] = volumesnapshotclass.New(factory.SnapshotSharedInformerFactory())
clusterResourceGetters[snapshotv1.SchemeGroupVersion.WithResource("volumesnapshotcontents")] = volumesnapshotcontent.New(factory.SnapshotSharedInformerFactory())
namespacedResourceGetters[rbacv1.SchemeGroupVersion.WithResource(iamv1alpha2.ResourcesPluralRoleBinding)] = rolebinding.New(factory.KubernetesSharedInformerFactory())
namespacedResourceGetters[rbacv1.SchemeGroupVersion.WithResource(iamv1alpha2.ResourcesPluralRole)] = role.New(factory.KubernetesSharedInformerFactory())
clusterResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "nodes"}] = node.New(factory.KubernetesSharedInformerFactory())
clusterResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "namespaces"}] = namespace.New(factory.KubernetesSharedInformerFactory())
clusterResourceGetters[schema.GroupVersionResource{Group: "apiextensions.k8s.io", Version: "v1", Resource: "customresourcedefinitions"}] = customresourcedefinition.New(factory.ApiExtensionSharedInformerFactory())
namespacedResourceGetters[schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}] = deployment.New(cache)
namespacedResourceGetters[schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "daemonsets"}] = daemonset.New(cache)
namespacedResourceGetters[schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "statefulsets"}] = statefulset.New(cache)
namespacedResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "services"}] = service.New(cache)
namespacedResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "configmaps"}] = configmap.New(cache)
namespacedResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "secrets"}] = secret.New(cache)
namespacedResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}] = pod.New(cache)
namespacedResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "serviceaccounts"}] = serviceaccount.New(cache)
namespacedResourceGetters[schema.GroupVersionResource{Group: "networking.k8s.io", Version: "v1", Resource: "ingresses"}] = ingress.New(cache)
namespacedResourceGetters[schema.GroupVersionResource{Group: "batch", Version: "v1", Resource: "jobs"}] = job.New(cache)
namespacedResourceGetters[schema.GroupVersionResource{Group: "batch", Version: "v1", Resource: "cronjobs"}] = cronjob.New(cache, k8sVersion)
namespacedResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumeclaims"}] = persistentvolumeclaim.New(cache)
namespacedResourceGetters[schema.GroupVersionResource{Group: "autoscaling", Version: "v2", Resource: "horizontalpodautoscalers"}] = hpa.New(cache, k8sVersion)
namespacedResourceGetters[rbacv1.SchemeGroupVersion.WithResource(iamv1beta1.ResourcesPluralRoleBinding)] = rolebinding.New(cache)
namespacedResourceGetters[rbacv1.SchemeGroupVersion.WithResource(iamv1beta1.ResourcesPluralRole)] = role.New(cache)
clusterResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumes"}] = persistentvolume.New(cache)
clusterResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "nodes"}] = node.New(cache)
clusterResourceGetters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "namespaces"}] = namespace.New(cache)
clusterResourceGetters[schema.GroupVersionResource{Group: "apiextensions.k8s.io", Version: "v1", Resource: "customresourcedefinitions"}] = customresourcedefinition.New(cache)
// kubesphere resources
namespacedResourceGetters[networkv1alpha1.SchemeGroupVersion.WithResource(networkv1alpha1.ResourcePluralIPPool)] = ippool.New(factory.KubeSphereSharedInformerFactory(), factory.KubernetesSharedInformerFactory())
clusterResourceGetters[devopsv1alpha3.SchemeGroupVersion.WithResource(devopsv1alpha3.ResourcePluralDevOpsProject)] = devops.New(factory.KubeSphereSharedInformerFactory())
clusterResourceGetters[tenantv1alpha1.SchemeGroupVersion.WithResource(tenantv1alpha1.ResourcePluralWorkspace)] = workspace.New(factory.KubeSphereSharedInformerFactory())
clusterResourceGetters[tenantv1alpha1.SchemeGroupVersion.WithResource(tenantv1alpha2.ResourcePluralWorkspaceTemplate)] = workspacetemplate.New(factory.KubeSphereSharedInformerFactory())
clusterResourceGetters[iamv1alpha2.SchemeGroupVersion.WithResource(iamv1alpha2.ResourcesPluralGlobalRole)] = globalrole.New(factory.KubeSphereSharedInformerFactory())
clusterResourceGetters[iamv1alpha2.SchemeGroupVersion.WithResource(iamv1alpha2.ResourcesPluralWorkspaceRole)] = workspacerole.New(factory.KubeSphereSharedInformerFactory())
clusterResourceGetters[iamv1alpha2.SchemeGroupVersion.WithResource(iamv1alpha2.ResourcesPluralUser)] = user.New(factory.KubeSphereSharedInformerFactory(), factory.KubernetesSharedInformerFactory())
clusterResourceGetters[iamv1alpha2.SchemeGroupVersion.WithResource(iamv1alpha2.ResourcesPluralGlobalRoleBinding)] = globalrolebinding.New(factory.KubeSphereSharedInformerFactory())
clusterResourceGetters[iamv1alpha2.SchemeGroupVersion.WithResource(iamv1alpha2.ResourcesPluralWorkspaceRoleBinding)] = workspacerolebinding.New(factory.KubeSphereSharedInformerFactory())
clusterResourceGetters[iamv1alpha2.SchemeGroupVersion.WithResource(iamv1alpha2.ResourcesPluralLoginRecord)] = loginrecord.New(factory.KubeSphereSharedInformerFactory())
clusterResourceGetters[iamv1alpha2.SchemeGroupVersion.WithResource(iamv1alpha2.ResourcePluralGroup)] = group.New(factory.KubeSphereSharedInformerFactory())
clusterResourceGetters[iamv1alpha2.SchemeGroupVersion.WithResource(iamv1alpha2.ResourcePluralGroupBinding)] = groupbinding.New(factory.KubeSphereSharedInformerFactory())
clusterResourceGetters[rbacv1.SchemeGroupVersion.WithResource(iamv1alpha2.ResourcesPluralClusterRole)] = clusterrole.New(factory.KubernetesSharedInformerFactory())
clusterResourceGetters[rbacv1.SchemeGroupVersion.WithResource(iamv1alpha2.ResourcesPluralClusterRoleBinding)] = clusterrolebinding.New(factory.KubernetesSharedInformerFactory())
clusterResourceGetters[clusterv1alpha1.SchemeGroupVersion.WithResource(clusterv1alpha1.ResourcesPluralCluster)] = cluster.New(factory.KubeSphereSharedInformerFactory())
clusterResourceGetters[notificationv2beta2.SchemeGroupVersion.WithResource(notificationv2beta2.ResourcesPluralNotificationManager)] = notification.NewNotificationManagerGetter(factory.KubeSphereSharedInformerFactory())
clusterResourceGetters[notificationv2beta2.SchemeGroupVersion.WithResource(notificationv2beta2.ResourcesPluralConfig)] = notification.NewNotificationConfigGetter(factory.KubeSphereSharedInformerFactory())
clusterResourceGetters[notificationv2beta2.SchemeGroupVersion.WithResource(notificationv2beta2.ResourcesPluralReceiver)] = notification.NewNotificationReceiverGetter(factory.KubeSphereSharedInformerFactory())
clusterResourceGetters[notificationv2beta2.SchemeGroupVersion.WithResource(notificationv2beta2.ResourcesPluralRouter)] = notification.NewNotificationRouterGetter(factory.KubeSphereSharedInformerFactory())
clusterResourceGetters[notificationv2beta2.SchemeGroupVersion.WithResource(notificationv2beta2.ResourcesPluralSilence)] = notification.NewNotificationSilenceGetter(factory.KubeSphereSharedInformerFactory())
clusterResourceGetters[monitoringdashboardv1alpha2.GroupVersion.WithResource("clusterdashboards")] = clusterdashboard.New(cache)
clusterResourceGetters[v1beta1.SchemeGroupVersion.WithResource(v1beta1.ResourcePluralWorkspace)] = workspace.New(cache)
clusterResourceGetters[v1beta1.SchemeGroupVersion.WithResource(tenantv1beta1.ResourcePluralWorkspaceTemplate)] = workspacetemplate.New(cache)
clusterResourceGetters[iamv1beta1.SchemeGroupVersion.WithResource(iamv1beta1.ResourcesPluralGlobalRole)] = globalrole.New(cache)
clusterResourceGetters[iamv1beta1.SchemeGroupVersion.WithResource(iamv1beta1.ResourcesPluralWorkspaceRole)] = workspacerole.New(cache)
clusterResourceGetters[iamv1beta1.SchemeGroupVersion.WithResource(iamv1beta1.ResourcesPluralUser)] = user.New(cache)
clusterResourceGetters[iamv1beta1.SchemeGroupVersion.WithResource(iamv1beta1.ResourcesPluralGlobalRoleBinding)] = globalrolebinding.New(cache)
clusterResourceGetters[iamv1beta1.SchemeGroupVersion.WithResource(iamv1beta1.ResourcesPluralWorkspaceRoleBinding)] = workspacerolebinding.New(cache)
clusterResourceGetters[iamv1beta1.SchemeGroupVersion.WithResource(iamv1beta1.ResourcesPluralLoginRecord)] = loginrecord.New(cache)
clusterResourceGetters[iamv1beta1.SchemeGroupVersion.WithResource(iamv1beta1.ResourcePluralGroup)] = group.New(cache)
clusterResourceGetters[iamv1beta1.SchemeGroupVersion.WithResource(iamv1beta1.ResourcePluralGroupBinding)] = groupbinding.New(cache)
clusterResourceGetters[rbacv1.SchemeGroupVersion.WithResource(iamv1beta1.ResourcesPluralClusterRole)] = clusterrole.New(cache)
clusterResourceGetters[rbacv1.SchemeGroupVersion.WithResource(iamv1beta1.ResourcesPluralClusterRoleBinding)] = clusterrolebinding.New(cache)
clusterResourceGetters[clusterv1alpha1.SchemeGroupVersion.WithResource(clusterv1alpha1.ResourcesPluralCluster)] = cluster.New(cache)
clusterResourceGetters[clusterv1alpha1.SchemeGroupVersion.WithResource(clusterv1alpha1.ResourcesPluralLabel)] = label.New(cache)
// federated resources
namespacedResourceGetters[typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedNamespace)] = federatednamespace.New(factory.KubeSphereSharedInformerFactory())
namespacedResourceGetters[typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedDeployment)] = federateddeployment.New(factory.KubeSphereSharedInformerFactory())
namespacedResourceGetters[typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedSecret)] = federatedsecret.New(factory.KubeSphereSharedInformerFactory())
namespacedResourceGetters[typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedConfigmap)] = federatedconfigmap.New(factory.KubeSphereSharedInformerFactory())
namespacedResourceGetters[typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedService)] = federatedservice.New(factory.KubeSphereSharedInformerFactory())
namespacedResourceGetters[typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedApplication)] = federatedapplication.New(factory.KubeSphereSharedInformerFactory())
namespacedResourceGetters[typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedPersistentVolumeClaim)] = federatedpersistentvolumeclaim.New(factory.KubeSphereSharedInformerFactory())
namespacedResourceGetters[typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedStatefulSet)] = federatedstatefulset.New(factory.KubeSphereSharedInformerFactory())
namespacedResourceGetters[typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedIngress)] = federatedingress.New(factory.KubeSphereSharedInformerFactory())
namespacedResourceGetters[monitoringdashboardv1alpha2.GroupVersion.WithResource("dashboards")] = dashboard.New(cache)
return &ResourceGetter{
return &Getter{
namespacedResourceGetters: namespacedResourceGetters,
clusterResourceGetters: clusterResourceGetters,
}
@@ -170,7 +112,7 @@ func NewResourceGetter(factory informers.InformerFactory, cache cache.Cache) *Re
// TryResource will retrieve a getter with resource name, it doesn't guarantee find resource with correct group version
// need to refactor this use schema.GroupVersionResource
func (r *ResourceGetter) TryResource(clusterScope bool, resource string) v1alpha3.Interface {
func (r *Getter) TryResource(clusterScope bool, resource string) v1alpha3.Interface {
if clusterScope {
for k, v := range r.clusterResourceGetters {
if k.Resource == resource {
@@ -186,7 +128,7 @@ func (r *ResourceGetter) TryResource(clusterScope bool, resource string) v1alpha
return nil
}
func (r *ResourceGetter) Get(resource, namespace, name string) (runtime.Object, error) {
func (r *Getter) Get(resource, namespace, name string) (runtime.Object, error) {
clusterScope := namespace == ""
getter := r.TryResource(clusterScope, resource)
if getter == nil {
@@ -195,7 +137,7 @@ func (r *ResourceGetter) Get(resource, namespace, name string) (runtime.Object,
return getter.Get(namespace, name)
}
func (r *ResourceGetter) List(resource, namespace string, query *query.Query) (*api.ListResult, error) {
func (r *Getter) List(resource, namespace string, query *query.Query) (*api.ListResult, error) {
clusterScope := namespace == ""
getter := r.TryResource(clusterScope, resource)
if getter == nil {

Some files were not shown because too many files have changed in this diff Show More