未验证 提交 dab0842a 编写于 作者: K KubeSphere CI Bot 提交者: GitHub

Merge pull request #3161 from RolandMa1986/feat-group-fedsync

enable multicluster sync for groups
......@@ -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 {
......
---
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: []
---
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: []
/*
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"`
}
/*
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"`
}
......@@ -74,6 +74,8 @@ func init() {
&FederatedStatefulSetList{},
&FederatedUser{},
&FederatedUserList{},
&FederatedGroup{},
&FederatedGroupList{},
&FederatedWorkspace{},
&FederatedWorkspaceList{})
}
......@@ -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
......
/*
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
}
/*
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
}
......@@ -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}
}
......
/*
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
}
/*
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
}
......@@ -28,6 +28,10 @@ type FederatedConfigMapExpansion interface{}
type FederatedDeploymentExpansion interface{}
type FederatedGroupExpansion interface{}
type FederatedGroupBindingExpansion interface{}
type FederatedIngressExpansion interface{}
type FederatedJobExpansion interface{}
......
......@@ -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)
}
......
......@@ -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"):
......
/*
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())
}
/*
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())
}
......@@ -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}
......
......@@ -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{}
......
/*
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
}
/*
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
}
......@@ -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
}
......@@ -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))
}
......@@ -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
}
......@@ -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)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册