diff --git a/cmd/controller-manager/app/controllers.go b/cmd/controller-manager/app/controllers.go index 973bd800f79276a36b74ae514a137f4f72d43354..360f275fd57a1b3155c5964d56e2b311f47e74cd 100644 --- a/cmd/controller-manager/app/controllers.go +++ b/cmd/controller-manager/app/controllers.go @@ -261,10 +261,14 @@ func addControllers( multiClusterEnabled) groupBindingController := groupbinding.NewController(client.Kubernetes(), client.KubeSphere(), - kubesphereInformer.Iam().V1alpha2().GroupBindings()) + kubesphereInformer.Iam().V1alpha2().GroupBindings(), + kubesphereInformer.Types().V1beta1().FederatedGroupBindings(), + multiClusterEnabled) groupController := group.NewController(client.Kubernetes(), client.KubeSphere(), - kubesphereInformer.Iam().V1alpha2().Groups()) + kubesphereInformer.Iam().V1alpha2().Groups(), + kubesphereInformer.Types().V1beta1().FederatedGroups(), + multiClusterEnabled) var clusterController manager.Runnable if multiClusterEnabled { diff --git a/config/crds/types.kubefed.io_federatedgroupbindings.yaml b/config/crds/types.kubefed.io_federatedgroupbindings.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ca70e07cb94b59e953125c81b32038159197b032 --- /dev/null +++ b/config/crds/types.kubefed.io_federatedgroupbindings.yaml @@ -0,0 +1,212 @@ +--- +apiVersion: core.kubefed.io/v1beta1 +kind: FederatedTypeConfig +metadata: + name: groupbindings.iam.kubesphere.io +spec: + federatedType: + group: types.kubefed.io + kind: FederatedGroupBinding + pluralName: federatedgroupbindings + scope: Cluster + version: v1beta1 + propagation: Enabled + targetType: + group: iam.kubesphere.io + kind: GroupBinding + pluralName: groupbindings + scope: Cluster + version: v1alpha2 +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: (devel) + creationTimestamp: null + name: federatedgroupbindings.types.kubefed.io +spec: + group: types.kubefed.io + names: + kind: FederatedGroupBinding + listKind: FederatedGroupBindingList + plural: federatedgroupbindings + singular: federatedgroupbinding + scope: Cluster + validation: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + overrides: + items: + properties: + clusterName: + type: string + clusterOverrides: + items: + properties: + op: + type: string + path: + type: string + value: + type: object + required: + - path + type: object + type: array + required: + - clusterName + type: object + type: array + placement: + properties: + clusterSelector: + description: A label selector is a label query over a set of resources. + The result of matchLabels and matchExpressions are ANDed. An empty + label selector matches all objects. A null label selector matches + no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement is a selector that + contains values, a key, and an operator that relates the + key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of string values. If the + operator is In or NotIn, the values array must be non-empty. + If the operator is Exists or DoesNotExist, the values + array must be empty. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. A single + {key,value} in the matchLabels map is equivalent to an element + of matchExpressions, whose key field is "key", the operator + is "In", and the values array contains only "value". The requirements + are ANDed. + type: object + type: object + clusters: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + type: object + template: + properties: + metadata: + type: object + groupRef: + description: GroupRef defines the desired relation of GroupBinding + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + type: object + users: + items: + type: string + type: array + type: object + required: + - placement + - template + type: object + status: + properties: + clusters: + items: + properties: + name: + type: string + status: + type: string + required: + - name + type: object + type: array + conditions: + items: + properties: + lastTransitionTime: + description: Last time the condition transit from one status to + another. + type: string + lastUpdateTime: + description: Last time reconciliation resulted in an error or + the last time a change was propagated to member clusters. + type: string + reason: + description: (brief) reason for the condition's last transition. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of cluster condition + type: string + required: + - status + - type + type: object + type: array + observedGeneration: + format: int64 + type: integer + type: object + required: + - spec + type: object + version: v1beta1 + versions: + - name: v1beta1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crds/types.kubefed.io_federatedgroups.yaml b/config/crds/types.kubefed.io_federatedgroups.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a987b7aaf4616b80f7ccdad2a9fabedab4f1a296 --- /dev/null +++ b/config/crds/types.kubefed.io_federatedgroups.yaml @@ -0,0 +1,200 @@ +--- +apiVersion: core.kubefed.io/v1beta1 +kind: FederatedTypeConfig +metadata: + name: groups.iam.kubesphere.io +spec: + federatedType: + group: types.kubefed.io + kind: FederatedGroup + pluralName: federatedgroups + scope: Cluster + version: v1beta1 + propagation: Enabled + targetType: + group: iam.kubesphere.io + kind: Group + pluralName: groups + scope: Cluster + version: v1alpha2 +--- +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: (devel) + creationTimestamp: null + name: federatedgroups.types.kubefed.io +spec: + group: types.kubefed.io + names: + kind: FederatedGroup + listKind: FederatedGroupList + plural: federatedgroups + singular: federatedgroup + scope: Cluster + validation: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + overrides: + items: + properties: + clusterName: + type: string + clusterOverrides: + items: + properties: + op: + type: string + path: + type: string + value: + type: object + required: + - path + type: object + type: array + required: + - clusterName + type: object + type: array + placement: + properties: + clusterSelector: + description: A label selector is a label query over a set of resources. + The result of matchLabels and matchExpressions are ANDed. An empty + label selector matches all objects. A null label selector matches + no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement is a selector that + contains values, a key, and an operator that relates the + key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of string values. If the + operator is In or NotIn, the values array must be non-empty. + If the operator is Exists or DoesNotExist, the values + array must be empty. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. A single + {key,value} in the matchLabels map is equivalent to an element + of matchExpressions, whose key field is "key", the operator + is "In", and the values array contains only "value". The requirements + are ANDed. + type: object + type: object + clusters: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + type: object + template: + properties: + spec: + description: GroupSpec defines the desired state of Group + type: object + type: object + required: + - placement + - template + type: object + status: + properties: + clusters: + items: + properties: + name: + type: string + status: + type: string + required: + - name + type: object + type: array + conditions: + items: + properties: + lastTransitionTime: + description: Last time the condition transit from one status to + another. + type: string + lastUpdateTime: + description: Last time reconciliation resulted in an error or + the last time a change was propagated to member clusters. + type: string + reason: + description: (brief) reason for the condition's last transition. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of cluster condition + type: string + required: + - status + - type + type: object + type: array + observedGeneration: + format: int64 + type: integer + type: object + required: + - spec + type: object + version: v1beta1 + versions: + - name: v1beta1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/pkg/apis/types/v1beta1/federatedgroup_types.go b/pkg/apis/types/v1beta1/federatedgroup_types.go new file mode 100644 index 0000000000000000000000000000000000000000..7efce4f3ea21ee2fd2aa3e0d8239ccb7954e8d40 --- /dev/null +++ b/pkg/apis/types/v1beta1/federatedgroup_types.go @@ -0,0 +1,60 @@ +/* +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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2" +) + +const ( + ResourcePluralFederatedGroup = "federatedgroups" + ResourceSingularFederatedGroup = "federatedgroup" + FederatedGroupKind = "FederatedGroup" +) + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:openapi-gen=true +type FederatedGroup struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec FederatedGroupSpec `json:"spec"` + + Status *GenericFederatedStatus `json:"status,omitempty"` +} + +type FederatedGroupSpec struct { + Template GroupTemplate `json:"template"` + Placement GenericPlacementFields `json:"placement"` + Overrides []GenericOverrideItem `json:"overrides,omitempty"` +} + +type GroupTemplate struct { + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec v1alpha2.GroupSpec `json:"spec,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// FederatedGroupList contains a list of federateduserlists +type FederatedGroupList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []FederatedGroup `json:"items"` +} diff --git a/pkg/apis/types/v1beta1/federatedgroupbinding_types.go b/pkg/apis/types/v1beta1/federatedgroupbinding_types.go new file mode 100644 index 0000000000000000000000000000000000000000..d81b32c2ffee25e5498750e870e4eba5e55b0743 --- /dev/null +++ b/pkg/apis/types/v1beta1/federatedgroupbinding_types.go @@ -0,0 +1,63 @@ +/* +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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2" +) + +const ( + ResourcePluralFederatedGroupBinding = "federatedgroupbindings" + ResourceSingularFederatedGroupBinding = "federatedgroupbinding" + FederatedGroupBindingKind = "FederatedGroupBinding" +) + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:openapi-gen=true +type FederatedGroupBinding struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec FederatedGroupBindingSpec `json:"spec"` + Status *GenericFederatedStatus `json:"status,omitempty"` +} + +type FederatedGroupBindingSpec struct { + Template GroupBindingTemplate `json:"template"` + Placement GenericPlacementFields `json:"placement"` + Overrides []GenericOverrideItem `json:"overrides,omitempty"` +} + +type GroupBindingTemplate struct { + metav1.ObjectMeta `json:"metadata,omitempty"` + // +optional + GroupRef v1alpha2.GroupRef `json:"groupRef,omitempty"` + + // +optional + Users []string `json:"users,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// FederatedGroupBindingList contains a list of federateduserlists +type FederatedGroupBindingList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []FederatedGroupBinding `json:"items"` +} diff --git a/pkg/apis/types/v1beta1/register.go b/pkg/apis/types/v1beta1/register.go index 346556ee87a4905088a8257f2f79ac3253f728c3..e2c6d50edd648cbae9d23d1e76237386395ba17f 100644 --- a/pkg/apis/types/v1beta1/register.go +++ b/pkg/apis/types/v1beta1/register.go @@ -74,6 +74,8 @@ func init() { &FederatedStatefulSetList{}, &FederatedUser{}, &FederatedUserList{}, + &FederatedGroup{}, + &FederatedGroupList{}, &FederatedWorkspace{}, &FederatedWorkspaceList{}) } diff --git a/pkg/apis/types/v1beta1/zz_generated.deepcopy.go b/pkg/apis/types/v1beta1/zz_generated.deepcopy.go index c2cfaec68f3226e32e62f94e004740811bba6f92..01c830c515f7bf27e974280dcd3dda8d9dcde054 100644 --- a/pkg/apis/types/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/types/v1beta1/zz_generated.deepcopy.go @@ -615,6 +615,186 @@ func (in *FederatedDeploymentSpec) DeepCopy() *FederatedDeploymentSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FederatedGroup) DeepCopyInto(out *FederatedGroup) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(GenericFederatedStatus) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederatedGroup. +func (in *FederatedGroup) DeepCopy() *FederatedGroup { + if in == nil { + return nil + } + out := new(FederatedGroup) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *FederatedGroup) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FederatedGroupBinding) DeepCopyInto(out *FederatedGroupBinding) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(GenericFederatedStatus) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederatedGroupBinding. +func (in *FederatedGroupBinding) DeepCopy() *FederatedGroupBinding { + if in == nil { + return nil + } + out := new(FederatedGroupBinding) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *FederatedGroupBinding) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FederatedGroupBindingList) DeepCopyInto(out *FederatedGroupBindingList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]FederatedGroupBinding, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederatedGroupBindingList. +func (in *FederatedGroupBindingList) DeepCopy() *FederatedGroupBindingList { + if in == nil { + return nil + } + out := new(FederatedGroupBindingList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *FederatedGroupBindingList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FederatedGroupBindingSpec) DeepCopyInto(out *FederatedGroupBindingSpec) { + *out = *in + in.Template.DeepCopyInto(&out.Template) + in.Placement.DeepCopyInto(&out.Placement) + if in.Overrides != nil { + in, out := &in.Overrides, &out.Overrides + *out = make([]GenericOverrideItem, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederatedGroupBindingSpec. +func (in *FederatedGroupBindingSpec) DeepCopy() *FederatedGroupBindingSpec { + if in == nil { + return nil + } + out := new(FederatedGroupBindingSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FederatedGroupList) DeepCopyInto(out *FederatedGroupList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]FederatedGroup, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederatedGroupList. +func (in *FederatedGroupList) DeepCopy() *FederatedGroupList { + if in == nil { + return nil + } + out := new(FederatedGroupList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *FederatedGroupList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FederatedGroupSpec) DeepCopyInto(out *FederatedGroupSpec) { + *out = *in + out.Template = in.Template + in.Placement.DeepCopyInto(&out.Placement) + if in.Overrides != nil { + in, out := &in.Overrides, &out.Overrides + *out = make([]GenericOverrideItem, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederatedGroupSpec. +func (in *FederatedGroupSpec) DeepCopy() *FederatedGroupSpec { + if in == nil { + return nil + } + out := new(FederatedGroupSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FederatedIngress) DeepCopyInto(out *FederatedIngress) { *out = *in @@ -1839,6 +2019,46 @@ func (in *GenericPlacementSpec) DeepCopy() *GenericPlacementSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GroupBindingTemplate) DeepCopyInto(out *GroupBindingTemplate) { + *out = *in + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.GroupRef = in.GroupRef + if in.Users != nil { + in, out := &in.Users, &out.Users + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GroupBindingTemplate. +func (in *GroupBindingTemplate) DeepCopy() *GroupBindingTemplate { + if in == nil { + return nil + } + out := new(GroupBindingTemplate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GroupTemplate) DeepCopyInto(out *GroupTemplate) { + *out = *in + out.Spec = in.Spec + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GroupTemplate. +func (in *GroupTemplate) DeepCopy() *GroupTemplate { + if in == nil { + return nil + } + out := new(GroupTemplate) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *IngressTemplate) DeepCopyInto(out *IngressTemplate) { *out = *in diff --git a/pkg/client/clientset/versioned/typed/types/v1beta1/fake/fake_federatedgroup.go b/pkg/client/clientset/versioned/typed/types/v1beta1/fake/fake_federatedgroup.go new file mode 100644 index 0000000000000000000000000000000000000000..fdee3b29a0e700e2006cb689b259b69707d542e8 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/types/v1beta1/fake/fake_federatedgroup.go @@ -0,0 +1,131 @@ +/* +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1beta1 "kubesphere.io/kubesphere/pkg/apis/types/v1beta1" +) + +// FakeFederatedGroups implements FederatedGroupInterface +type FakeFederatedGroups struct { + Fake *FakeTypesV1beta1 +} + +var federatedgroupsResource = schema.GroupVersionResource{Group: "types.kubefed.io", Version: "v1beta1", Resource: "federatedgroups"} + +var federatedgroupsKind = schema.GroupVersionKind{Group: "types.kubefed.io", Version: "v1beta1", Kind: "FederatedGroup"} + +// Get takes name of the federatedGroup, and returns the corresponding federatedGroup object, and an error if there is any. +func (c *FakeFederatedGroups) Get(name string, options v1.GetOptions) (result *v1beta1.FederatedGroup, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(federatedgroupsResource, name), &v1beta1.FederatedGroup{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.FederatedGroup), err +} + +// List takes label and field selectors, and returns the list of FederatedGroups that match those selectors. +func (c *FakeFederatedGroups) List(opts v1.ListOptions) (result *v1beta1.FederatedGroupList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(federatedgroupsResource, federatedgroupsKind, opts), &v1beta1.FederatedGroupList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1beta1.FederatedGroupList{ListMeta: obj.(*v1beta1.FederatedGroupList).ListMeta} + for _, item := range obj.(*v1beta1.FederatedGroupList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested federatedGroups. +func (c *FakeFederatedGroups) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(federatedgroupsResource, opts)) +} + +// Create takes the representation of a federatedGroup and creates it. Returns the server's representation of the federatedGroup, and an error, if there is any. +func (c *FakeFederatedGroups) Create(federatedGroup *v1beta1.FederatedGroup) (result *v1beta1.FederatedGroup, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(federatedgroupsResource, federatedGroup), &v1beta1.FederatedGroup{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.FederatedGroup), err +} + +// Update takes the representation of a federatedGroup and updates it. Returns the server's representation of the federatedGroup, and an error, if there is any. +func (c *FakeFederatedGroups) Update(federatedGroup *v1beta1.FederatedGroup) (result *v1beta1.FederatedGroup, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(federatedgroupsResource, federatedGroup), &v1beta1.FederatedGroup{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.FederatedGroup), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeFederatedGroups) UpdateStatus(federatedGroup *v1beta1.FederatedGroup) (*v1beta1.FederatedGroup, error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(federatedgroupsResource, "status", federatedGroup), &v1beta1.FederatedGroup{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.FederatedGroup), err +} + +// Delete takes name of the federatedGroup and deletes it. Returns an error if one occurs. +func (c *FakeFederatedGroups) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(federatedgroupsResource, name), &v1beta1.FederatedGroup{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeFederatedGroups) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(federatedgroupsResource, listOptions) + + _, err := c.Fake.Invokes(action, &v1beta1.FederatedGroupList{}) + return err +} + +// Patch applies the patch and returns the patched federatedGroup. +func (c *FakeFederatedGroups) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.FederatedGroup, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(federatedgroupsResource, name, pt, data, subresources...), &v1beta1.FederatedGroup{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.FederatedGroup), err +} diff --git a/pkg/client/clientset/versioned/typed/types/v1beta1/fake/fake_federatedgroupbinding.go b/pkg/client/clientset/versioned/typed/types/v1beta1/fake/fake_federatedgroupbinding.go new file mode 100644 index 0000000000000000000000000000000000000000..88967a19496f580be25a0cfdaa52edb0ef7e8e4c --- /dev/null +++ b/pkg/client/clientset/versioned/typed/types/v1beta1/fake/fake_federatedgroupbinding.go @@ -0,0 +1,131 @@ +/* +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1beta1 "kubesphere.io/kubesphere/pkg/apis/types/v1beta1" +) + +// FakeFederatedGroupBindings implements FederatedGroupBindingInterface +type FakeFederatedGroupBindings struct { + Fake *FakeTypesV1beta1 +} + +var federatedgroupbindingsResource = schema.GroupVersionResource{Group: "types.kubefed.io", Version: "v1beta1", Resource: "federatedgroupbindings"} + +var federatedgroupbindingsKind = schema.GroupVersionKind{Group: "types.kubefed.io", Version: "v1beta1", Kind: "FederatedGroupBinding"} + +// Get takes name of the federatedGroupBinding, and returns the corresponding federatedGroupBinding object, and an error if there is any. +func (c *FakeFederatedGroupBindings) Get(name string, options v1.GetOptions) (result *v1beta1.FederatedGroupBinding, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(federatedgroupbindingsResource, name), &v1beta1.FederatedGroupBinding{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.FederatedGroupBinding), err +} + +// List takes label and field selectors, and returns the list of FederatedGroupBindings that match those selectors. +func (c *FakeFederatedGroupBindings) List(opts v1.ListOptions) (result *v1beta1.FederatedGroupBindingList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(federatedgroupbindingsResource, federatedgroupbindingsKind, opts), &v1beta1.FederatedGroupBindingList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1beta1.FederatedGroupBindingList{ListMeta: obj.(*v1beta1.FederatedGroupBindingList).ListMeta} + for _, item := range obj.(*v1beta1.FederatedGroupBindingList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested federatedGroupBindings. +func (c *FakeFederatedGroupBindings) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(federatedgroupbindingsResource, opts)) +} + +// Create takes the representation of a federatedGroupBinding and creates it. Returns the server's representation of the federatedGroupBinding, and an error, if there is any. +func (c *FakeFederatedGroupBindings) Create(federatedGroupBinding *v1beta1.FederatedGroupBinding) (result *v1beta1.FederatedGroupBinding, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(federatedgroupbindingsResource, federatedGroupBinding), &v1beta1.FederatedGroupBinding{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.FederatedGroupBinding), err +} + +// Update takes the representation of a federatedGroupBinding and updates it. Returns the server's representation of the federatedGroupBinding, and an error, if there is any. +func (c *FakeFederatedGroupBindings) Update(federatedGroupBinding *v1beta1.FederatedGroupBinding) (result *v1beta1.FederatedGroupBinding, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(federatedgroupbindingsResource, federatedGroupBinding), &v1beta1.FederatedGroupBinding{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.FederatedGroupBinding), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeFederatedGroupBindings) UpdateStatus(federatedGroupBinding *v1beta1.FederatedGroupBinding) (*v1beta1.FederatedGroupBinding, error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(federatedgroupbindingsResource, "status", federatedGroupBinding), &v1beta1.FederatedGroupBinding{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.FederatedGroupBinding), err +} + +// Delete takes name of the federatedGroupBinding and deletes it. Returns an error if one occurs. +func (c *FakeFederatedGroupBindings) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(federatedgroupbindingsResource, name), &v1beta1.FederatedGroupBinding{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeFederatedGroupBindings) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(federatedgroupbindingsResource, listOptions) + + _, err := c.Fake.Invokes(action, &v1beta1.FederatedGroupBindingList{}) + return err +} + +// Patch applies the patch and returns the patched federatedGroupBinding. +func (c *FakeFederatedGroupBindings) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.FederatedGroupBinding, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(federatedgroupbindingsResource, name, pt, data, subresources...), &v1beta1.FederatedGroupBinding{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.FederatedGroupBinding), err +} diff --git a/pkg/client/clientset/versioned/typed/types/v1beta1/fake/fake_types_client.go b/pkg/client/clientset/versioned/typed/types/v1beta1/fake/fake_types_client.go index e68701eddf3f54bab53682aee4f0163443671982..944ab5f4e0dcc01906b6880223f95094b4edd3d6 100644 --- a/pkg/client/clientset/versioned/typed/types/v1beta1/fake/fake_types_client.go +++ b/pkg/client/clientset/versioned/typed/types/v1beta1/fake/fake_types_client.go @@ -48,6 +48,14 @@ func (c *FakeTypesV1beta1) FederatedDeployments(namespace string) v1beta1.Federa return &FakeFederatedDeployments{c, namespace} } +func (c *FakeTypesV1beta1) FederatedGroups() v1beta1.FederatedGroupInterface { + return &FakeFederatedGroups{c} +} + +func (c *FakeTypesV1beta1) FederatedGroupBindings() v1beta1.FederatedGroupBindingInterface { + return &FakeFederatedGroupBindings{c} +} + func (c *FakeTypesV1beta1) FederatedIngresses(namespace string) v1beta1.FederatedIngressInterface { return &FakeFederatedIngresses{c, namespace} } diff --git a/pkg/client/clientset/versioned/typed/types/v1beta1/federatedgroup.go b/pkg/client/clientset/versioned/typed/types/v1beta1/federatedgroup.go new file mode 100644 index 0000000000000000000000000000000000000000..86c74a2e4aee7b257a66d06f2a473c48268063f5 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/types/v1beta1/federatedgroup.go @@ -0,0 +1,180 @@ +/* +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1beta1 + +import ( + "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1beta1 "kubesphere.io/kubesphere/pkg/apis/types/v1beta1" + scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme" +) + +// FederatedGroupsGetter has a method to return a FederatedGroupInterface. +// A group's client should implement this interface. +type FederatedGroupsGetter interface { + FederatedGroups() FederatedGroupInterface +} + +// FederatedGroupInterface has methods to work with FederatedGroup resources. +type FederatedGroupInterface interface { + Create(*v1beta1.FederatedGroup) (*v1beta1.FederatedGroup, error) + Update(*v1beta1.FederatedGroup) (*v1beta1.FederatedGroup, error) + UpdateStatus(*v1beta1.FederatedGroup) (*v1beta1.FederatedGroup, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1beta1.FederatedGroup, error) + List(opts v1.ListOptions) (*v1beta1.FederatedGroupList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.FederatedGroup, err error) + FederatedGroupExpansion +} + +// federatedGroups implements FederatedGroupInterface +type federatedGroups struct { + client rest.Interface +} + +// newFederatedGroups returns a FederatedGroups +func newFederatedGroups(c *TypesV1beta1Client) *federatedGroups { + return &federatedGroups{ + client: c.RESTClient(), + } +} + +// Get takes name of the federatedGroup, and returns the corresponding federatedGroup object, and an error if there is any. +func (c *federatedGroups) Get(name string, options v1.GetOptions) (result *v1beta1.FederatedGroup, err error) { + result = &v1beta1.FederatedGroup{} + err = c.client.Get(). + Resource("federatedgroups"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of FederatedGroups that match those selectors. +func (c *federatedGroups) List(opts v1.ListOptions) (result *v1beta1.FederatedGroupList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1beta1.FederatedGroupList{} + err = c.client.Get(). + Resource("federatedgroups"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested federatedGroups. +func (c *federatedGroups) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("federatedgroups"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a federatedGroup and creates it. Returns the server's representation of the federatedGroup, and an error, if there is any. +func (c *federatedGroups) Create(federatedGroup *v1beta1.FederatedGroup) (result *v1beta1.FederatedGroup, err error) { + result = &v1beta1.FederatedGroup{} + err = c.client.Post(). + Resource("federatedgroups"). + Body(federatedGroup). + Do(). + Into(result) + return +} + +// Update takes the representation of a federatedGroup and updates it. Returns the server's representation of the federatedGroup, and an error, if there is any. +func (c *federatedGroups) Update(federatedGroup *v1beta1.FederatedGroup) (result *v1beta1.FederatedGroup, err error) { + result = &v1beta1.FederatedGroup{} + err = c.client.Put(). + Resource("federatedgroups"). + Name(federatedGroup.Name). + Body(federatedGroup). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *federatedGroups) UpdateStatus(federatedGroup *v1beta1.FederatedGroup) (result *v1beta1.FederatedGroup, err error) { + result = &v1beta1.FederatedGroup{} + err = c.client.Put(). + Resource("federatedgroups"). + Name(federatedGroup.Name). + SubResource("status"). + Body(federatedGroup). + Do(). + Into(result) + return +} + +// Delete takes name of the federatedGroup and deletes it. Returns an error if one occurs. +func (c *federatedGroups) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Resource("federatedgroups"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *federatedGroups) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("federatedgroups"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched federatedGroup. +func (c *federatedGroups) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.FederatedGroup, err error) { + result = &v1beta1.FederatedGroup{} + err = c.client.Patch(pt). + Resource("federatedgroups"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/client/clientset/versioned/typed/types/v1beta1/federatedgroupbinding.go b/pkg/client/clientset/versioned/typed/types/v1beta1/federatedgroupbinding.go new file mode 100644 index 0000000000000000000000000000000000000000..7af32521daf19e6d98f9b2e6ab1abef8d7ac3fab --- /dev/null +++ b/pkg/client/clientset/versioned/typed/types/v1beta1/federatedgroupbinding.go @@ -0,0 +1,180 @@ +/* +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1beta1 + +import ( + "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1beta1 "kubesphere.io/kubesphere/pkg/apis/types/v1beta1" + scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme" +) + +// FederatedGroupBindingsGetter has a method to return a FederatedGroupBindingInterface. +// A group's client should implement this interface. +type FederatedGroupBindingsGetter interface { + FederatedGroupBindings() FederatedGroupBindingInterface +} + +// FederatedGroupBindingInterface has methods to work with FederatedGroupBinding resources. +type FederatedGroupBindingInterface interface { + Create(*v1beta1.FederatedGroupBinding) (*v1beta1.FederatedGroupBinding, error) + Update(*v1beta1.FederatedGroupBinding) (*v1beta1.FederatedGroupBinding, error) + UpdateStatus(*v1beta1.FederatedGroupBinding) (*v1beta1.FederatedGroupBinding, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1beta1.FederatedGroupBinding, error) + List(opts v1.ListOptions) (*v1beta1.FederatedGroupBindingList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.FederatedGroupBinding, err error) + FederatedGroupBindingExpansion +} + +// federatedGroupBindings implements FederatedGroupBindingInterface +type federatedGroupBindings struct { + client rest.Interface +} + +// newFederatedGroupBindings returns a FederatedGroupBindings +func newFederatedGroupBindings(c *TypesV1beta1Client) *federatedGroupBindings { + return &federatedGroupBindings{ + client: c.RESTClient(), + } +} + +// Get takes name of the federatedGroupBinding, and returns the corresponding federatedGroupBinding object, and an error if there is any. +func (c *federatedGroupBindings) Get(name string, options v1.GetOptions) (result *v1beta1.FederatedGroupBinding, err error) { + result = &v1beta1.FederatedGroupBinding{} + err = c.client.Get(). + Resource("federatedgroupbindings"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of FederatedGroupBindings that match those selectors. +func (c *federatedGroupBindings) List(opts v1.ListOptions) (result *v1beta1.FederatedGroupBindingList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1beta1.FederatedGroupBindingList{} + err = c.client.Get(). + Resource("federatedgroupbindings"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested federatedGroupBindings. +func (c *federatedGroupBindings) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("federatedgroupbindings"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a federatedGroupBinding and creates it. Returns the server's representation of the federatedGroupBinding, and an error, if there is any. +func (c *federatedGroupBindings) Create(federatedGroupBinding *v1beta1.FederatedGroupBinding) (result *v1beta1.FederatedGroupBinding, err error) { + result = &v1beta1.FederatedGroupBinding{} + err = c.client.Post(). + Resource("federatedgroupbindings"). + Body(federatedGroupBinding). + Do(). + Into(result) + return +} + +// Update takes the representation of a federatedGroupBinding and updates it. Returns the server's representation of the federatedGroupBinding, and an error, if there is any. +func (c *federatedGroupBindings) Update(federatedGroupBinding *v1beta1.FederatedGroupBinding) (result *v1beta1.FederatedGroupBinding, err error) { + result = &v1beta1.FederatedGroupBinding{} + err = c.client.Put(). + Resource("federatedgroupbindings"). + Name(federatedGroupBinding.Name). + Body(federatedGroupBinding). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *federatedGroupBindings) UpdateStatus(federatedGroupBinding *v1beta1.FederatedGroupBinding) (result *v1beta1.FederatedGroupBinding, err error) { + result = &v1beta1.FederatedGroupBinding{} + err = c.client.Put(). + Resource("federatedgroupbindings"). + Name(federatedGroupBinding.Name). + SubResource("status"). + Body(federatedGroupBinding). + Do(). + Into(result) + return +} + +// Delete takes name of the federatedGroupBinding and deletes it. Returns an error if one occurs. +func (c *federatedGroupBindings) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Resource("federatedgroupbindings"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *federatedGroupBindings) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("federatedgroupbindings"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched federatedGroupBinding. +func (c *federatedGroupBindings) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.FederatedGroupBinding, err error) { + result = &v1beta1.FederatedGroupBinding{} + err = c.client.Patch(pt). + Resource("federatedgroupbindings"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/client/clientset/versioned/typed/types/v1beta1/generated_expansion.go b/pkg/client/clientset/versioned/typed/types/v1beta1/generated_expansion.go index d1a188ffd6c0ae612a913cddd6f64eade72f96af..fb11e731f2411bc0a0c902f15ef6e9bcd6454d96 100644 --- a/pkg/client/clientset/versioned/typed/types/v1beta1/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/types/v1beta1/generated_expansion.go @@ -28,6 +28,10 @@ type FederatedConfigMapExpansion interface{} type FederatedDeploymentExpansion interface{} +type FederatedGroupExpansion interface{} + +type FederatedGroupBindingExpansion interface{} + type FederatedIngressExpansion interface{} type FederatedJobExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/types/v1beta1/types_client.go b/pkg/client/clientset/versioned/typed/types/v1beta1/types_client.go index 86e8dae95f2b93e8807634d139960446b62d2a15..156c7352d5f041746ff9716ab1abb262918cf337 100644 --- a/pkg/client/clientset/versioned/typed/types/v1beta1/types_client.go +++ b/pkg/client/clientset/versioned/typed/types/v1beta1/types_client.go @@ -31,6 +31,8 @@ type TypesV1beta1Interface interface { FederatedClusterRoleBindingsGetter FederatedConfigMapsGetter FederatedDeploymentsGetter + FederatedGroupsGetter + FederatedGroupBindingsGetter FederatedIngressesGetter FederatedJobsGetter FederatedLimitRangesGetter @@ -69,6 +71,14 @@ func (c *TypesV1beta1Client) FederatedDeployments(namespace string) FederatedDep return newFederatedDeployments(c, namespace) } +func (c *TypesV1beta1Client) FederatedGroups() FederatedGroupInterface { + return newFederatedGroups(c) +} + +func (c *TypesV1beta1Client) FederatedGroupBindings() FederatedGroupBindingInterface { + return newFederatedGroupBindings(c) +} + func (c *TypesV1beta1Client) FederatedIngresses(namespace string) FederatedIngressInterface { return newFederatedIngresses(c, namespace) } diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index c62e4e5a5f208f8bfde40f9aed000b0ecb422cac..f37d5673eb7061c446f6ec01a64b63380c375ea6 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -149,6 +149,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Types().V1beta1().FederatedConfigMaps().Informer()}, nil case v1beta1.SchemeGroupVersion.WithResource("federateddeployments"): return &genericInformer{resource: resource.GroupResource(), informer: f.Types().V1beta1().FederatedDeployments().Informer()}, nil + case v1beta1.SchemeGroupVersion.WithResource("federatedgroups"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Types().V1beta1().FederatedGroups().Informer()}, nil + case v1beta1.SchemeGroupVersion.WithResource("federatedgroupbindings"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Types().V1beta1().FederatedGroupBindings().Informer()}, nil case v1beta1.SchemeGroupVersion.WithResource("federatedingresses"): return &genericInformer{resource: resource.GroupResource(), informer: f.Types().V1beta1().FederatedIngresses().Informer()}, nil case v1beta1.SchemeGroupVersion.WithResource("federatedjobs"): diff --git a/pkg/client/informers/externalversions/types/v1beta1/federatedgroup.go b/pkg/client/informers/externalversions/types/v1beta1/federatedgroup.go new file mode 100644 index 0000000000000000000000000000000000000000..cf7fde4a61ff980a40b1e7c9173644ab4ca069a7 --- /dev/null +++ b/pkg/client/informers/externalversions/types/v1beta1/federatedgroup.go @@ -0,0 +1,88 @@ +/* +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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1beta1 + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + typesv1beta1 "kubesphere.io/kubesphere/pkg/apis/types/v1beta1" + versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" + v1beta1 "kubesphere.io/kubesphere/pkg/client/listers/types/v1beta1" +) + +// FederatedGroupInformer provides access to a shared informer and lister for +// FederatedGroups. +type FederatedGroupInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1beta1.FederatedGroupLister +} + +type federatedGroupInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewFederatedGroupInformer constructs a new informer for FederatedGroup type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFederatedGroupInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredFederatedGroupInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredFederatedGroupInformer constructs a new informer for FederatedGroup type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredFederatedGroupInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TypesV1beta1().FederatedGroups().List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TypesV1beta1().FederatedGroups().Watch(options) + }, + }, + &typesv1beta1.FederatedGroup{}, + resyncPeriod, + indexers, + ) +} + +func (f *federatedGroupInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredFederatedGroupInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *federatedGroupInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&typesv1beta1.FederatedGroup{}, f.defaultInformer) +} + +func (f *federatedGroupInformer) Lister() v1beta1.FederatedGroupLister { + return v1beta1.NewFederatedGroupLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/types/v1beta1/federatedgroupbinding.go b/pkg/client/informers/externalversions/types/v1beta1/federatedgroupbinding.go new file mode 100644 index 0000000000000000000000000000000000000000..8fe9a1b5e2dc1af886138f2f4c4726062e7f3cc4 --- /dev/null +++ b/pkg/client/informers/externalversions/types/v1beta1/federatedgroupbinding.go @@ -0,0 +1,88 @@ +/* +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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1beta1 + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + typesv1beta1 "kubesphere.io/kubesphere/pkg/apis/types/v1beta1" + versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" + v1beta1 "kubesphere.io/kubesphere/pkg/client/listers/types/v1beta1" +) + +// FederatedGroupBindingInformer provides access to a shared informer and lister for +// FederatedGroupBindings. +type FederatedGroupBindingInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1beta1.FederatedGroupBindingLister +} + +type federatedGroupBindingInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewFederatedGroupBindingInformer constructs a new informer for FederatedGroupBinding type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFederatedGroupBindingInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredFederatedGroupBindingInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredFederatedGroupBindingInformer constructs a new informer for FederatedGroupBinding type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredFederatedGroupBindingInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TypesV1beta1().FederatedGroupBindings().List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TypesV1beta1().FederatedGroupBindings().Watch(options) + }, + }, + &typesv1beta1.FederatedGroupBinding{}, + resyncPeriod, + indexers, + ) +} + +func (f *federatedGroupBindingInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredFederatedGroupBindingInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *federatedGroupBindingInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&typesv1beta1.FederatedGroupBinding{}, f.defaultInformer) +} + +func (f *federatedGroupBindingInformer) Lister() v1beta1.FederatedGroupBindingLister { + return v1beta1.NewFederatedGroupBindingLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/types/v1beta1/interface.go b/pkg/client/informers/externalversions/types/v1beta1/interface.go index 5652eb85ee6dbb5e959d2fbcf44a772c807640f5..f0f0e2f4c94477bd37836bd10145cd77ede52e61 100644 --- a/pkg/client/informers/externalversions/types/v1beta1/interface.go +++ b/pkg/client/informers/externalversions/types/v1beta1/interface.go @@ -34,6 +34,10 @@ type Interface interface { FederatedConfigMaps() FederatedConfigMapInformer // FederatedDeployments returns a FederatedDeploymentInformer. FederatedDeployments() FederatedDeploymentInformer + // FederatedGroups returns a FederatedGroupInformer. + FederatedGroups() FederatedGroupInformer + // FederatedGroupBindings returns a FederatedGroupBindingInformer. + FederatedGroupBindings() FederatedGroupBindingInformer // FederatedIngresses returns a FederatedIngressInformer. FederatedIngresses() FederatedIngressInformer // FederatedJobs returns a FederatedJobInformer. @@ -94,6 +98,16 @@ func (v *version) FederatedDeployments() FederatedDeploymentInformer { return &federatedDeploymentInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } +// FederatedGroups returns a FederatedGroupInformer. +func (v *version) FederatedGroups() FederatedGroupInformer { + return &federatedGroupInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + +// FederatedGroupBindings returns a FederatedGroupBindingInformer. +func (v *version) FederatedGroupBindings() FederatedGroupBindingInformer { + return &federatedGroupBindingInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + // FederatedIngresses returns a FederatedIngressInformer. func (v *version) FederatedIngresses() FederatedIngressInformer { return &federatedIngressInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/client/listers/types/v1beta1/expansion_generated.go b/pkg/client/listers/types/v1beta1/expansion_generated.go index 1658262ff658410caf0d29cc1edc4446887786e1..b4f334a1bb8f8b168bef4f29ebeaf68378662021 100644 --- a/pkg/client/listers/types/v1beta1/expansion_generated.go +++ b/pkg/client/listers/types/v1beta1/expansion_generated.go @@ -58,6 +58,14 @@ type FederatedDeploymentListerExpansion interface{} // FederatedDeploymentNamespaceLister. type FederatedDeploymentNamespaceListerExpansion interface{} +// FederatedGroupListerExpansion allows custom methods to be added to +// FederatedGroupLister. +type FederatedGroupListerExpansion interface{} + +// FederatedGroupBindingListerExpansion allows custom methods to be added to +// FederatedGroupBindingLister. +type FederatedGroupBindingListerExpansion interface{} + // FederatedIngressListerExpansion allows custom methods to be added to // FederatedIngressLister. type FederatedIngressListerExpansion interface{} diff --git a/pkg/client/listers/types/v1beta1/federatedgroup.go b/pkg/client/listers/types/v1beta1/federatedgroup.go new file mode 100644 index 0000000000000000000000000000000000000000..e979ec28ccc3de5a6b2bc3d101b1cc3bc4f68aae --- /dev/null +++ b/pkg/client/listers/types/v1beta1/federatedgroup.go @@ -0,0 +1,65 @@ +/* +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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1beta1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1beta1 "kubesphere.io/kubesphere/pkg/apis/types/v1beta1" +) + +// FederatedGroupLister helps list FederatedGroups. +type FederatedGroupLister interface { + // List lists all FederatedGroups in the indexer. + List(selector labels.Selector) (ret []*v1beta1.FederatedGroup, err error) + // Get retrieves the FederatedGroup from the index for a given name. + Get(name string) (*v1beta1.FederatedGroup, error) + FederatedGroupListerExpansion +} + +// federatedGroupLister implements the FederatedGroupLister interface. +type federatedGroupLister struct { + indexer cache.Indexer +} + +// NewFederatedGroupLister returns a new FederatedGroupLister. +func NewFederatedGroupLister(indexer cache.Indexer) FederatedGroupLister { + return &federatedGroupLister{indexer: indexer} +} + +// List lists all FederatedGroups in the indexer. +func (s *federatedGroupLister) List(selector labels.Selector) (ret []*v1beta1.FederatedGroup, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1beta1.FederatedGroup)) + }) + return ret, err +} + +// Get retrieves the FederatedGroup from the index for a given name. +func (s *federatedGroupLister) Get(name string) (*v1beta1.FederatedGroup, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1beta1.Resource("federatedgroup"), name) + } + return obj.(*v1beta1.FederatedGroup), nil +} diff --git a/pkg/client/listers/types/v1beta1/federatedgroupbinding.go b/pkg/client/listers/types/v1beta1/federatedgroupbinding.go new file mode 100644 index 0000000000000000000000000000000000000000..484415111768d5b2f9764d47b5d36d44f8b40951 --- /dev/null +++ b/pkg/client/listers/types/v1beta1/federatedgroupbinding.go @@ -0,0 +1,65 @@ +/* +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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1beta1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1beta1 "kubesphere.io/kubesphere/pkg/apis/types/v1beta1" +) + +// FederatedGroupBindingLister helps list FederatedGroupBindings. +type FederatedGroupBindingLister interface { + // List lists all FederatedGroupBindings in the indexer. + List(selector labels.Selector) (ret []*v1beta1.FederatedGroupBinding, err error) + // Get retrieves the FederatedGroupBinding from the index for a given name. + Get(name string) (*v1beta1.FederatedGroupBinding, error) + FederatedGroupBindingListerExpansion +} + +// federatedGroupBindingLister implements the FederatedGroupBindingLister interface. +type federatedGroupBindingLister struct { + indexer cache.Indexer +} + +// NewFederatedGroupBindingLister returns a new FederatedGroupBindingLister. +func NewFederatedGroupBindingLister(indexer cache.Indexer) FederatedGroupBindingLister { + return &federatedGroupBindingLister{indexer: indexer} +} + +// List lists all FederatedGroupBindings in the indexer. +func (s *federatedGroupBindingLister) List(selector labels.Selector) (ret []*v1beta1.FederatedGroupBinding, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1beta1.FederatedGroupBinding)) + }) + return ret, err +} + +// Get retrieves the FederatedGroupBinding from the index for a given name. +func (s *federatedGroupBindingLister) Get(name string) (*v1beta1.FederatedGroupBinding, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1beta1.Resource("federatedgroupbinding"), name) + } + return obj.(*v1beta1.FederatedGroupBinding), nil +} diff --git a/pkg/controller/group/group_controller.go b/pkg/controller/group/group_controller.go index 57b9e2e9658ba89cdd1ac2481b8b308f03ac73b5..1a01a7d34dc5c48cca1f1aefc065a0b2aefa6981 100644 --- a/pkg/controller/group/group_controller.go +++ b/pkg/controller/group/group_controller.go @@ -18,6 +18,7 @@ package group import ( "fmt" + "reflect" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -33,11 +34,16 @@ import ( "k8s.io/client-go/util/workqueue" "k8s.io/klog" iam1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2" + fedv1beta1types "kubesphere.io/kubesphere/pkg/apis/types/v1beta1" kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned" iamv1alpha2informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/iam/v1alpha2" + fedv1beta1informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/types/v1beta1" iamv1alpha1listers "kubesphere.io/kubesphere/pkg/client/listers/iam/v1alpha2" + fedv1beta1lister "kubesphere.io/kubesphere/pkg/client/listers/types/v1beta1" + "kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/controller/utils/controller" "kubesphere.io/kubesphere/pkg/utils/sliceutil" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" ) const ( @@ -49,16 +55,21 @@ const ( type Controller struct { controller.BaseController - scheme *runtime.Scheme - k8sClient kubernetes.Interface - ksClient kubesphere.Interface - groupInformer iamv1alpha2informers.GroupInformer - groupLister iamv1alpha1listers.GroupLister - recorder record.EventRecorder + scheme *runtime.Scheme + k8sClient kubernetes.Interface + ksClient kubesphere.Interface + groupInformer iamv1alpha2informers.GroupInformer + groupLister iamv1alpha1listers.GroupLister + recorder record.EventRecorder + federatedGroupInformer fedv1beta1informers.FederatedGroupInformer + federatedGroupLister fedv1beta1lister.FederatedGroupLister + multiClusterEnabled bool } // NewController creates Group Controller instance -func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface, groupInformer iamv1alpha2informers.GroupInformer) *Controller { +func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface, groupInformer iamv1alpha2informers.GroupInformer, + federatedGroupInformer fedv1beta1informers.FederatedGroupInformer, + multiClusterEnabled bool) *Controller { klog.V(4).Info("Creating event broadcaster") eventBroadcaster := record.NewBroadcaster() @@ -70,12 +81,20 @@ func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface Synced: []cache.InformerSynced{groupInformer.Informer().HasSynced}, Name: controllerName, }, - recorder: eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: controllerName}), - k8sClient: k8sClient, - ksClient: ksClient, - groupInformer: groupInformer, - groupLister: groupInformer.Lister(), + recorder: eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: controllerName}), + k8sClient: k8sClient, + ksClient: ksClient, + groupInformer: groupInformer, + groupLister: groupInformer.Lister(), + federatedGroupInformer: federatedGroupInformer, + federatedGroupLister: federatedGroupInformer.Lister(), + multiClusterEnabled: multiClusterEnabled, } + + if ctl.multiClusterEnabled { + ctl.Synced = append(ctl.Synced, ctl.federatedGroupInformer.Informer().HasSynced) + } + ctl.Handler = ctl.reconcile klog.Info("Setting up event handlers") @@ -106,10 +125,27 @@ func (c *Controller) reconcile(key string) error { return err } if group.ObjectMeta.DeletionTimestamp.IsZero() { + var g *iam1alpha2.Group if !sliceutil.HasString(group.Finalizers, finalizer) { - group.ObjectMeta.Finalizers = append(group.ObjectMeta.Finalizers, finalizer) + g = group.DeepCopy() + g.ObjectMeta.Finalizers = append(g.ObjectMeta.Finalizers, finalizer) + } - if group, err = c.ksClient.IamV1alpha2().Groups().Update(group); err != nil { + if c.multiClusterEnabled { + // Ensure not controlled by Kubefed + if group.Labels == nil || group.Labels[constants.KubefedManagedLabel] != "false" { + if g == nil { + g = group.DeepCopy() + } + if g.Labels == nil { + g.Labels = make(map[string]string, 0) + } + g.Labels[constants.KubefedManagedLabel] = "false" + } + } + + if g != nil { + if _, err = c.ksClient.IamV1alpha2().Groups().Update(g); err != nil { return err } // Skip reconcile when group is updated. @@ -139,6 +175,14 @@ func (c *Controller) reconcile(key string) error { return nil } + // synchronization through kubefed-controller when multi cluster is enabled + if c.multiClusterEnabled { + if err = c.multiClusterSync(group); err != nil { + klog.Error(err) + return err + } + } + c.recorder.Event(group, corev1.EventTypeNormal, successSynced, messageResourceSynced) return nil } @@ -192,3 +236,54 @@ func (c *Controller) deleteRoleBindings(group *iam1alpha2.Group) error { return nil } + +func (c *Controller) multiClusterSync(group *iam1alpha2.Group) error { + + obj, err := c.federatedGroupLister.Get(group.Name) + if err != nil { + if errors.IsNotFound(err) { + return c.createFederatedGroup(group) + } + klog.Error(err) + return err + } + + if !reflect.DeepEqual(obj.Spec.Template.Labels, group.Labels) { + + obj.Spec.Template.Labels = group.Labels + + if _, err = c.ksClient.TypesV1beta1().FederatedGroups().Update(obj); err != nil { + return err + } + } + return nil +} + +func (c *Controller) createFederatedGroup(group *iam1alpha2.Group) error { + federatedGroup := &fedv1beta1types.FederatedGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: group.Name, + }, + Spec: fedv1beta1types.FederatedGroupSpec{ + Template: fedv1beta1types.GroupTemplate{ + ObjectMeta: metav1.ObjectMeta{ + Labels: group.Labels, + }, + Spec: group.Spec, + }, + Placement: fedv1beta1types.GenericPlacementFields{ + ClusterSelector: &metav1.LabelSelector{}, + }, + }, + } + + // must bind group lifecycle + err := controllerutil.SetControllerReference(group, federatedGroup, scheme.Scheme) + if err != nil { + return err + } + if _, err = c.ksClient.TypesV1beta1().FederatedGroups().Create(federatedGroup); err != nil { + return err + } + return nil +} diff --git a/pkg/controller/group/group_controller_test.go b/pkg/controller/group/group_controller_test.go index facac217c8e72eb06acf1239812e18050fe5de19..66dffc2c78e12b065ac75f69e5f508016e77a069 100644 --- a/pkg/controller/group/group_controller_test.go +++ b/pkg/controller/group/group_controller_test.go @@ -21,17 +21,22 @@ import ( "testing" "time" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/diff" kubeinformers "k8s.io/client-go/informers" k8sfake "k8s.io/client-go/kubernetes/fake" + "k8s.io/client-go/kubernetes/scheme" core "k8s.io/client-go/testing" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" v1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2" + fedv1beta1types "kubesphere.io/kubesphere/pkg/apis/types/v1beta1" "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake" ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions" + "kubesphere.io/kubesphere/pkg/constants" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -41,13 +46,18 @@ var ( noResyncPeriodFunc = func() time.Duration { return 0 } ) +func init() { + v1alpha2.AddToScheme(scheme.Scheme) +} + type fixture struct { t *testing.T ksclient *fake.Clientset k8sclient *k8sfake.Clientset // Objects to put in the store. - groupLister []*v1alpha2.Group + groupLister []*v1alpha2.Group + fedgroupLister []*fedv1beta1types.FederatedGroup // Actions expected to happen on the client. kubeactions []core.Action actions []core.Action @@ -66,7 +76,7 @@ func newFixture(t *testing.T) *fixture { func newGroup(name string) *v1alpha2.Group { return &v1alpha2.Group{ - TypeMeta: metav1.TypeMeta{APIVersion: v1alpha2.SchemeGroupVersion.String()}, + TypeMeta: metav1.TypeMeta{APIVersion: v1alpha2.SchemeGroupVersion.String(), Kind: "Group"}, ObjectMeta: metav1.ObjectMeta{ Name: name, }, @@ -74,6 +84,38 @@ func newGroup(name string) *v1alpha2.Group { } } +func newUnmanagedGroup(name string) *v1alpha2.Group { + return &v1alpha2.Group{ + TypeMeta: metav1.TypeMeta{APIVersion: v1alpha2.SchemeGroupVersion.String(), Kind: "Group"}, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Labels: map[string]string{constants.KubefedManagedLabel: "false"}, + Finalizers: []string{"finalizers.kubesphere.io/groups"}, + }, + Spec: v1alpha2.GroupSpec{}, + } +} + +func newFederatedGroup(group *v1alpha2.Group) *fedv1beta1types.FederatedGroup { + return &fedv1beta1types.FederatedGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: group.Name, + }, + Spec: fedv1beta1types.FederatedGroupSpec{ + Template: fedv1beta1types.GroupTemplate{ + ObjectMeta: metav1.ObjectMeta{ + Labels: group.Labels, + }, + Spec: group.Spec, + }, + Placement: fedv1beta1types.GenericPlacementFields{ + ClusterSelector: &metav1.LabelSelector{}, + }, + }, + } + +} + func (f *fixture) newController() (*Controller, ksinformers.SharedInformerFactory, kubeinformers.SharedInformerFactory) { f.ksclient = fake.NewSimpleClientset(f.objects...) f.k8sclient = k8sfake.NewSimpleClientset(f.kubeobjects...) @@ -88,8 +130,16 @@ func (f *fixture) newController() (*Controller, ksinformers.SharedInformerFactor } } + for _, group := range f.fedgroupLister { + err := ksinformers.Types().V1beta1().FederatedGroups().Informer().GetIndexer().Add(group) + if err != nil { + f.t.Errorf("add federated group:%s", err) + } + } + c := NewController(f.k8sclient, f.ksclient, - ksinformers.Iam().V1alpha2().Groups()) + ksinformers.Iam().V1alpha2().Groups(), + ksinformers.Types().V1beta1().FederatedGroups(), true) c.recorder = &record.FakeRecorder{} return c, ksinformers, k8sinformers @@ -177,10 +227,8 @@ func checkAction(expected, actual core.Action, t *testing.T) { e, _ := expected.(core.UpdateActionImpl) expObject := e.GetObject() object := a.GetObject() - expUser := expObject.(*v1alpha2.Group) - group := object.(*v1alpha2.Group) - if !reflect.DeepEqual(expUser, group) { + if !reflect.DeepEqual(expObject, object) { t.Errorf("Action %s %s has wrong object\nDiff:\n %s", a.GetVerb(), a.GetResource().Resource, diff.ObjectGoPrintSideBySide(expObject, object)) } @@ -193,6 +241,15 @@ func checkAction(expected, actual core.Action, t *testing.T) { t.Errorf("Action %s %s has wrong patch\nDiff:\n %s", a.GetVerb(), a.GetResource().Resource, diff.ObjectGoPrintSideBySide(expPatch, patch)) } + case core.DeleteCollectionActionImpl: + e, _ := expected.(core.DeleteCollectionActionImpl) + exp := e.GetListRestrictions() + target := a.GetListRestrictions() + if !reflect.DeepEqual(exp, target) { + t.Errorf("Action %s %s has wrong Query\nDiff:\n %s", + a.GetVerb(), a.GetResource().Resource, diff.ObjectGoPrintSideBySide(exp, target)) + } + default: t.Errorf("Uncaptured Action %s %s, you should explicitly add a case to capture it", actual.GetVerb(), actual.GetResource().Resource) @@ -205,7 +262,13 @@ func checkAction(expected, actual core.Action, t *testing.T) { func filterInformerActions(actions []core.Action) []core.Action { var ret []core.Action for _, action := range actions { - if !action.Matches("update", "groups") { + if len(action.GetNamespace()) == 0 && + (action.Matches("list", "groups") || + action.Matches("watch", "groups") || + action.Matches("list", "groups") || + action.Matches("list", "namespaces") || + action.Matches("list", "federatedgroups") || + action.Matches("watch", "federatedgroups")) { continue } ret = append(ret, action) @@ -216,14 +279,47 @@ func filterInformerActions(actions []core.Action) []core.Action { func (f *fixture) expectUpdateGroupsFinalizerAction(group *v1alpha2.Group) { expect := group.DeepCopy() + if expect.Labels == nil { + expect.Labels = make(map[string]string, 0) + } expect.Finalizers = []string{"finalizers.kubesphere.io/groups"} + expect.Labels[constants.KubefedManagedLabel] = "false" action := core.NewUpdateAction(schema.GroupVersionResource{Resource: "groups"}, "", expect) f.actions = append(f.actions, action) } +func (f *fixture) expectCreateFederatedGroupsAction(group *v1alpha2.Group) { + federatedGroup := newFederatedGroup(group) + + controllerutil.SetControllerReference(group, federatedGroup, scheme.Scheme) + + actionCreate := core.NewCreateAction(schema.GroupVersionResource{Resource: "federatedgroups"}, "", federatedGroup) + f.actions = append(f.actions, actionCreate) +} + +func (f *fixture) expectUpdateFederatedGroupsAction(group *v1alpha2.Group) { + g := newFederatedGroup(group) + controllerutil.SetControllerReference(group, g, scheme.Scheme) + actionCreate := core.NewUpdateAction(schema.GroupVersionResource{Group: "types.kubefed.io", Version: "v1beta1", Resource: "federatedgroups"}, "", g) + f.actions = append(f.actions, actionCreate) +} + func (f *fixture) expectUpdateGroupsDeleteAction(group *v1alpha2.Group) { expect := group.DeepCopy() expect.Finalizers = []string{} + listOptions := metav1.ListOptions{ + LabelSelector: labels.SelectorFromSet(labels.Set{v1alpha2.GroupReferenceLabel: group.Name}).String(), + } + + actionDelete := core.NewDeleteCollectionAction(schema.GroupVersionResource{Resource: "groupbindings"}, "", listOptions) + f.actions = append(f.actions, actionDelete) + + actionDelete = core.NewDeleteCollectionAction(schema.GroupVersionResource{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "clusterrolebindings"}, "", listOptions) + f.kubeactions = append(f.kubeactions, actionDelete) + + actionDelete = core.NewDeleteCollectionAction(schema.GroupVersionResource{Resource: "workspacerolebindings"}, "", listOptions) + f.actions = append(f.actions, actionDelete) + action := core.NewUpdateAction(schema.GroupVersionResource{Resource: "groups"}, "", expect) f.actions = append(f.actions, action) } @@ -239,18 +335,8 @@ func getKey(group *v1alpha2.Group, t *testing.T) string { func TestDeletesGroup(t *testing.T) { f := newFixture(t) - group := newGroup("test") - - f.groupLister = append(f.groupLister, group) - f.objects = append(f.objects, group) - - f.expectUpdateGroupsFinalizerAction(group) - f.run(getKey(group, t)) + deletedGroup := newUnmanagedGroup("test") - f = newFixture(t) - - deletedGroup := group.DeepCopy() - deletedGroup.Finalizers = []string{"finalizers.kubesphere.io/groups"} now := metav1.Now() deletedGroup.ObjectMeta.DeletionTimestamp = &now @@ -270,3 +356,34 @@ func TestDoNothing(t *testing.T) { f.expectUpdateGroupsFinalizerAction(group) f.run(getKey(group, t)) } + +func TestFederetedGroupCreate(t *testing.T) { + f := newFixture(t) + + group := newUnmanagedGroup("test") + + f.groupLister = append(f.groupLister, group) + f.objects = append(f.objects, group) + + f.expectCreateFederatedGroupsAction(group) + f.run(getKey(group, t)) +} + +func TestFederetedGroupUpdate(t *testing.T) { + f := newFixture(t) + + group := newUnmanagedGroup("test") + + federatedGroup := newFederatedGroup(group.DeepCopy()) + controllerutil.SetControllerReference(group, federatedGroup, scheme.Scheme) + + f.fedgroupLister = append(f.fedgroupLister, federatedGroup) + f.objects = append(f.objects, federatedGroup) + + group.Labels["foo"] = "bar" + f.groupLister = append(f.groupLister, group) + f.objects = append(f.objects, group) + + f.expectUpdateFederatedGroupsAction(group.DeepCopy()) + f.run(getKey(group, t)) +} diff --git a/pkg/controller/groupbinding/groupbinding_controller.go b/pkg/controller/groupbinding/groupbinding_controller.go index ee0bc0f3fecca52e4d09d507a76ef7decd541604..f3ae8c9cba7a3936742bfa42ae3aafec92a85196 100644 --- a/pkg/controller/groupbinding/groupbinding_controller.go +++ b/pkg/controller/groupbinding/groupbinding_controller.go @@ -19,6 +19,8 @@ package groupbinding import ( "fmt" + "reflect" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -32,12 +34,17 @@ import ( "k8s.io/client-go/util/workqueue" "k8s.io/klog" iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2" + fedv1beta1types "kubesphere.io/kubesphere/pkg/apis/types/v1beta1" kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned" iamv1alpha2informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/iam/v1alpha2" + fedv1beta1informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/types/v1beta1" iamv1alpha2listers "kubesphere.io/kubesphere/pkg/client/listers/iam/v1alpha2" + fedv1beta1lister "kubesphere.io/kubesphere/pkg/client/listers/types/v1beta1" + "kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/controller/utils/controller" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" ) const ( @@ -49,16 +56,21 @@ const ( type Controller struct { controller.BaseController - scheme *runtime.Scheme - k8sClient kubernetes.Interface - ksClient kubesphere.Interface - groupBindingInformer iamv1alpha2informers.GroupBindingInformer - groupBindingLister iamv1alpha2listers.GroupBindingLister - recorder record.EventRecorder + scheme *runtime.Scheme + k8sClient kubernetes.Interface + ksClient kubesphere.Interface + groupBindingInformer iamv1alpha2informers.GroupBindingInformer + groupBindingLister iamv1alpha2listers.GroupBindingLister + recorder record.EventRecorder + federatedGroupBindingInformer fedv1beta1informers.FederatedGroupBindingInformer + federatedGroupBindingLister fedv1beta1lister.FederatedGroupBindingLister + multiClusterEnabled bool } // NewController creates GroupBinding Controller instance -func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface, groupBindingInformer iamv1alpha2informers.GroupBindingInformer) *Controller { +func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface, + groupBindingInformer iamv1alpha2informers.GroupBindingInformer, + federatedGroupBindingInformer fedv1beta1informers.FederatedGroupBindingInformer, multiClusterEnabled bool) *Controller { klog.V(4).Info("Creating event broadcaster") eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(klog.Infof) @@ -70,13 +82,19 @@ func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface Synced: []cache.InformerSynced{groupBindingInformer.Informer().HasSynced}, Name: controllerName, }, - k8sClient: k8sClient, - ksClient: ksClient, - groupBindingInformer: groupBindingInformer, - groupBindingLister: groupBindingInformer.Lister(), - recorder: recorder, + k8sClient: k8sClient, + ksClient: ksClient, + groupBindingInformer: groupBindingInformer, + groupBindingLister: groupBindingInformer.Lister(), + federatedGroupBindingInformer: federatedGroupBindingInformer, + federatedGroupBindingLister: federatedGroupBindingInformer.Lister(), + multiClusterEnabled: multiClusterEnabled, + recorder: recorder, } ctl.Handler = ctl.reconcile + if ctl.multiClusterEnabled { + ctl.Synced = append(ctl.Synced, ctl.federatedGroupBindingInformer.Informer().HasSynced) + } klog.Info("Setting up event handlers") groupBindingInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: ctl.Enqueue, @@ -101,14 +119,32 @@ func (c *Controller) reconcile(key string) error { return err } if groupBinding.ObjectMeta.DeletionTimestamp.IsZero() { + var g *iamv1alpha2.GroupBinding if !sliceutil.HasString(groupBinding.Finalizers, finalizer) { - groupBinding.ObjectMeta.Finalizers = append(groupBinding.ObjectMeta.Finalizers, finalizer) - if groupBinding, err = c.ksClient.IamV1alpha2().GroupBindings().Update(groupBinding); err != nil { + g = groupBinding.DeepCopy() + g.ObjectMeta.Finalizers = append(g.ObjectMeta.Finalizers, finalizer) + } + + if c.multiClusterEnabled { + // Ensure not controlled by Kubefed + if groupBinding.Labels == nil || groupBinding.Labels[constants.KubefedManagedLabel] != "false" { + if g == nil { + g = groupBinding.DeepCopy() + } + if g.Labels == nil { + g.Labels = make(map[string]string, 0) + } + g.Labels[constants.KubefedManagedLabel] = "false" + } + } + if g != nil { + if groupBinding, err = c.ksClient.IamV1alpha2().GroupBindings().Update(g); err != nil { return err } - // Skip reconcile when groupbinding is updated. + // Skip reconcile when group is updated. return nil } + } else { // The object is being deleted if sliceutil.HasString(groupBinding.ObjectMeta.Finalizers, finalizer) { @@ -133,6 +169,14 @@ func (c *Controller) reconcile(key string) error { return err } + // synchronization through kubefed-controller when multi cluster is enabled + if c.multiClusterEnabled { + if err = c.multiClusterSync(groupBinding); err != nil { + klog.Error(err) + return err + } + } + c.recorder.Event(groupBinding, corev1.EventTypeNormal, successSynced, messageResourceSynced) return nil } @@ -204,3 +248,65 @@ func (c *Controller) patchUser(user *iamv1alpha2.User, groups []string) error { } return nil } + +func (c *Controller) multiClusterSync(groupBinding *iamv1alpha2.GroupBinding) error { + + fedGroupBinding, err := c.federatedGroupBindingLister.Get(groupBinding.Name) + + if err != nil { + if errors.IsNotFound(err) { + return c.createFederatedGroupBinding(groupBinding) + } + klog.Error(err) + return err + } + + if !reflect.DeepEqual(fedGroupBinding.Spec.Template.GroupRef, groupBinding.GroupRef) || + !reflect.DeepEqual(fedGroupBinding.Spec.Template.Users, groupBinding.Users) || + !reflect.DeepEqual(fedGroupBinding.Spec.Template.Labels, groupBinding.Labels) { + + fedGroupBinding.Spec.Template.GroupRef = groupBinding.GroupRef + fedGroupBinding.Spec.Template.Users = groupBinding.Users + fedGroupBinding.Spec.Template.Labels = groupBinding.Labels + + if _, err = c.ksClient.TypesV1beta1().FederatedGroupBindings().Update(fedGroupBinding); err != nil { + return err + } + } + + return nil +} + +func (c *Controller) createFederatedGroupBinding(groupBinding *iamv1alpha2.GroupBinding) error { + federatedGroup := &fedv1beta1types.FederatedGroupBinding{ + TypeMeta: metav1.TypeMeta{ + Kind: fedv1beta1types.FederatedGroupBindingKind, + APIVersion: fedv1beta1types.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: groupBinding.Name, + }, + Spec: fedv1beta1types.FederatedGroupBindingSpec{ + Template: fedv1beta1types.GroupBindingTemplate{ + ObjectMeta: metav1.ObjectMeta{ + Labels: groupBinding.Labels, + }, + GroupRef: groupBinding.GroupRef, + Users: groupBinding.Users, + }, + Placement: fedv1beta1types.GenericPlacementFields{ + ClusterSelector: &metav1.LabelSelector{}, + }, + }, + } + + // must bind groupBinding lifecycle + err := controllerutil.SetControllerReference(groupBinding, federatedGroup, scheme.Scheme) + if err != nil { + return err + } + if _, err = c.ksClient.TypesV1beta1().FederatedGroupBindings().Create(federatedGroup); err != nil { + return err + } + return nil +} diff --git a/pkg/controller/groupbinding/groupbinding_controller_test.go b/pkg/controller/groupbinding/groupbinding_controller_test.go index 91fcc5c00990374de71188e61aab9c654a7372f0..cdfc3e32a5938beec71861cbcbbf2f750de153ca 100644 --- a/pkg/controller/groupbinding/groupbinding_controller_test.go +++ b/pkg/controller/groupbinding/groupbinding_controller_test.go @@ -22,20 +22,24 @@ import ( "testing" "time" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/diff" kubeinformers "k8s.io/client-go/informers" k8sfake "k8s.io/client-go/kubernetes/fake" + "k8s.io/client-go/kubernetes/scheme" core "k8s.io/client-go/testing" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" + iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2" v1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2" + fedv1beta1types "kubesphere.io/kubesphere/pkg/apis/types/v1beta1" "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake" ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "kubesphere.io/kubesphere/pkg/constants" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" ) var ( @@ -43,14 +47,19 @@ var ( noResyncPeriodFunc = func() time.Duration { return 0 } ) +func init() { + v1alpha2.AddToScheme(scheme.Scheme) +} + type fixture struct { t *testing.T ksclient *fake.Clientset k8sclient *k8sfake.Clientset // Objects to put in the store. - groupBindingLister []*v1alpha2.GroupBinding - userLister []*v1alpha2.User + groupBindingLister []*v1alpha2.GroupBinding + fedgroupBindingLister []*fedv1beta1types.FederatedGroupBinding + userLister []*v1alpha2.User // Actions expected to happen on the client. kubeactions []core.Action actions []core.Action @@ -94,6 +103,30 @@ func newUser(name string) *v1alpha2.User { } } +func newFederatedGroupBinding(groupBinding *iamv1alpha2.GroupBinding) *fedv1beta1types.FederatedGroupBinding { + return &fedv1beta1types.FederatedGroupBinding{ + TypeMeta: metav1.TypeMeta{ + Kind: fedv1beta1types.FederatedGroupBindingKind, + APIVersion: fedv1beta1types.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: groupBinding.Name, + }, + Spec: fedv1beta1types.FederatedGroupBindingSpec{ + Template: fedv1beta1types.GroupBindingTemplate{ + ObjectMeta: metav1.ObjectMeta{ + Labels: groupBinding.Labels, + }, + GroupRef: groupBinding.GroupRef, + Users: groupBinding.Users, + }, + Placement: fedv1beta1types.GenericPlacementFields{ + ClusterSelector: &metav1.LabelSelector{}, + }, + }, + } +} + func (f *fixture) newController() (*Controller, ksinformers.SharedInformerFactory, kubeinformers.SharedInformerFactory) { f.ksclient = fake.NewSimpleClientset(f.objects...) f.k8sclient = k8sfake.NewSimpleClientset(f.kubeobjects...) @@ -116,7 +149,8 @@ func (f *fixture) newController() (*Controller, ksinformers.SharedInformerFactor } c := NewController(f.k8sclient, f.ksclient, - ksinformers.Iam().V1alpha2().GroupBindings()) + ksinformers.Iam().V1alpha2().GroupBindings(), + ksinformers.Types().V1beta1().FederatedGroupBindings(), true) c.Synced = []cache.InformerSynced{alwaysReady} c.recorder = &record.FakeRecorder{} @@ -236,6 +270,7 @@ func filterInformerActions(actions []core.Action) []core.Action { if len(action.GetNamespace()) == 0 && (action.Matches("list", "groupbindings") || action.Matches("watch", "groupbindings") || + action.Matches("list", "federatedgroupbindings") || action.Matches("list", "users") || action.Matches("watch", "users") || action.Matches("get", "users")) { @@ -250,6 +285,7 @@ func filterInformerActions(actions []core.Action) []core.Action { func (f *fixture) expectUpdateGroupsFinalizerAction(groupBinding *v1alpha2.GroupBinding) { expect := groupBinding.DeepCopy() expect.Finalizers = []string{"finalizers.kubesphere.io/groupsbindings"} + expect.Labels = map[string]string{constants.KubefedManagedLabel: "false"} action := core.NewUpdateAction(schema.GroupVersionResource{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "groupbindings"}, "", expect) f.actions = append(f.actions, action) } @@ -270,6 +306,15 @@ func (f *fixture) expectPatchUserAction(user *v1alpha2.User, groups []string) { f.actions = append(f.actions, core.NewPatchAction(schema.GroupVersionResource{Group: "iam.kubesphere.io", Resource: "users", Version: "v1alpha2"}, user.Namespace, user.Name, patch.Type(), patchData)) } +func (f *fixture) expectCreateFederatedGroupBindingsAction(groupBinding *v1alpha2.GroupBinding) { + b := newFederatedGroupBinding(groupBinding) + + controllerutil.SetControllerReference(groupBinding, b, scheme.Scheme) + + actionCreate := core.NewCreateAction(schema.GroupVersionResource{Group: "types.kubefed.io", Version: "v1beta1", Resource: "federatedgroupbindings"}, "", b) + f.actions = append(f.actions, actionCreate) +} + func getKey(groupBinding *v1alpha2.GroupBinding, t *testing.T) string { key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(groupBinding) if err != nil { @@ -285,6 +330,7 @@ func TestCreatesGroupBinding(t *testing.T) { users := []string{"user1"} groupbinding := newGroupBinding("test", users) groupbinding.ObjectMeta.Finalizers = append(groupbinding.ObjectMeta.Finalizers, finalizer) + groupbinding.Labels = map[string]string{constants.KubefedManagedLabel: "false"} f.groupBindingLister = append(f.groupBindingLister, groupbinding) f.objects = append(f.objects, groupbinding) @@ -294,7 +340,9 @@ func TestCreatesGroupBinding(t *testing.T) { f.objects = append(f.objects, user) excepctGroups := []string{"test"} + f.expectPatchUserAction(user, excepctGroups) + f.expectCreateFederatedGroupBindingsAction(groupbinding) f.run(getKey(groupbinding, t)) } @@ -326,6 +374,7 @@ func TestDeletesGroupBinding(t *testing.T) { func TestDoNothing(t *testing.T) { f := newFixture(t) + users := []string{"user1"} groupBinding := newGroupBinding("test", users)