提交 e8c1acdc 编写于 作者: H hongming

fix workspacetemplate patch API not working

Signed-off-by: Nhongming <talonwan@yunify.com>
上级 fd4790a6
......@@ -21,7 +21,6 @@ import (
"k8s.io/client-go/tools/cache"
"k8s.io/klog"
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
tenantv1alpha2 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha2"
authoptions "kubesphere.io/kubesphere/pkg/apiserver/authentication/options"
"kubesphere.io/kubesphere/pkg/controller/application"
"kubesphere.io/kubesphere/pkg/controller/certificatesigningrequest"
......@@ -159,9 +158,9 @@ func addControllers(
kubernetesInformer.Apps().V1().StatefulSets())
var fedUserCache, fedGlobalRoleBindingCache, fedGlobalRoleCache,
fedWorkspaceCache, fedWorkspaceRoleCache, fedWorkspaceRoleBindingCache cache.Store
fedWorkspaceRoleCache, fedWorkspaceRoleBindingCache cache.Store
var fedUserCacheController, fedGlobalRoleBindingCacheController, fedGlobalRoleCacheController,
fedWorkspaceCacheController, fedWorkspaceRoleCacheController, fedWorkspaceRoleBindingCacheController cache.Controller
fedWorkspaceRoleCacheController, fedWorkspaceRoleBindingCacheController cache.Controller
if multiClusterEnabled {
fedUserClient, err := util.NewResourceClient(client.Config(), &iamv1alpha2.FedUserResource)
......@@ -179,11 +178,6 @@ func addControllers(
klog.Error(err)
return err
}
fedWorkspaceClient, err := util.NewResourceClient(client.Config(), &tenantv1alpha2.FedWorkspaceResource)
if err != nil {
klog.Error(err)
return err
}
fedWorkspaceRoleClient, err := util.NewResourceClient(client.Config(), &iamv1alpha2.FedWorkspaceRoleResource)
if err != nil {
klog.Error(err)
......@@ -198,14 +192,12 @@ func addControllers(
fedUserCache, fedUserCacheController = util.NewResourceInformer(fedUserClient, "", &iamv1alpha2.FedUserResource, func(object runtime.Object) {})
fedGlobalRoleCache, fedGlobalRoleCacheController = util.NewResourceInformer(fedGlobalRoleClient, "", &iamv1alpha2.FedGlobalRoleResource, func(object runtime.Object) {})
fedGlobalRoleBindingCache, fedGlobalRoleBindingCacheController = util.NewResourceInformer(fedGlobalRoleBindingClient, "", &iamv1alpha2.FedGlobalRoleBindingResource, func(object runtime.Object) {})
fedWorkspaceCache, fedWorkspaceCacheController = util.NewResourceInformer(fedWorkspaceClient, "", &tenantv1alpha2.FedWorkspaceResource, func(object runtime.Object) {})
fedWorkspaceRoleCache, fedWorkspaceRoleCacheController = util.NewResourceInformer(fedWorkspaceRoleClient, "", &iamv1alpha2.FedWorkspaceRoleResource, func(object runtime.Object) {})
fedWorkspaceRoleBindingCache, fedWorkspaceRoleBindingCacheController = util.NewResourceInformer(fedWorkspaceRoleBindingClient, "", &iamv1alpha2.FedWorkspaceRoleBindingResource, func(object runtime.Object) {})
go fedUserCacheController.Run(stopCh)
go fedGlobalRoleCacheController.Run(stopCh)
go fedGlobalRoleBindingCacheController.Run(stopCh)
go fedWorkspaceCacheController.Run(stopCh)
go fedWorkspaceRoleCacheController.Run(stopCh)
go fedWorkspaceRoleBindingCacheController.Run(stopCh)
}
......@@ -255,7 +247,8 @@ func addControllers(
kubesphereInformer.Tenant().V1alpha1().Workspaces(),
kubesphereInformer.Iam().V1alpha2().RoleBases(),
kubesphereInformer.Iam().V1alpha2().WorkspaceRoles(),
fedWorkspaceCache, fedWorkspaceCacheController, multiClusterEnabled)
kubesphereInformer.Types().V1beta1().FederatedWorkspaces(),
multiClusterEnabled)
var clusterController manager.Runnable
if multiClusterEnabled {
......
......@@ -18,30 +18,13 @@ package v1alpha2
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
typesv1alpha1 "kubesphere.io/kubesphere/pkg/apis/types/v1beta1"
)
const (
ResourceKindWorkspaceTemplate = "WorkspaceTemplate"
ResourceSingularWorkspaceTemplate = "workspacetemplate"
ResourcePluralWorkspaceTemplate = "workspacetemplates"
ResourcesPluralFedWorkspace = "federatedworkspaces"
ResourcesSingularFedWorkspace = "federatedworkspace"
FedWorkspaceKind = "FederatedWorkspace"
fedResourceGroup = "types.kubefed.io"
fedResourceVersion = "v1beta1"
)
var (
FedWorkspaceResource = metav1.APIResource{
Name: ResourcesPluralFedWorkspace,
SingularName: ResourcesSingularFedWorkspace,
Namespaced: false,
Group: fedResourceGroup,
Version: fedResourceVersion,
Kind: FedWorkspaceKind,
}
)
// +genclient
......@@ -54,42 +37,7 @@ var (
type WorkspaceTemplate struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec WorkspaceTemplateSpec `json:"spec,omitempty"`
}
type WorkspaceTemplateSpec struct {
Template Template `json:"template"`
Placement Placement `json:"placement"`
Overrides []Override `json:"overrides,omitempty"`
}
type Template struct {
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec v1alpha1.WorkspaceSpec `json:"spec"`
}
type Placement struct {
Clusters []Cluster `json:"clusters,omitempty"`
ClusterSelector *ClusterSelector `json:"clusterSelector,omitempty"`
}
type ClusterSelector struct {
MatchLabels map[string]string `json:"matchLabels,omitempty"`
}
type Cluster struct {
Name string `json:"name"`
}
type Override struct {
ClusterName string `json:"clusterName"`
ClusterOverrides []ClusterOverride `json:"clusterOverrides"`
}
type ClusterOverride struct {
Path string `json:"path"`
Op string `json:"op,omitempty"`
Value runtime.RawExtension `json:"value"`
Spec typesv1alpha1.FederatedWorkspaceSpec `json:"spec,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
......@@ -105,9 +53,3 @@ type WorkspaceTemplateList struct {
func init() {
SchemeBuilder.Register(&WorkspaceTemplate{}, &WorkspaceTemplateList{})
}
type FederatedWorkspace struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec WorkspaceTemplateSpec `json:"spec"`
}
......@@ -24,148 +24,6 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Cluster) DeepCopyInto(out *Cluster) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Cluster.
func (in *Cluster) DeepCopy() *Cluster {
if in == nil {
return nil
}
out := new(Cluster)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterOverride) DeepCopyInto(out *ClusterOverride) {
*out = *in
in.Value.DeepCopyInto(&out.Value)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterOverride.
func (in *ClusterOverride) DeepCopy() *ClusterOverride {
if in == nil {
return nil
}
out := new(ClusterOverride)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterSelector) DeepCopyInto(out *ClusterSelector) {
*out = *in
if in.MatchLabels != nil {
in, out := &in.MatchLabels, &out.MatchLabels
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterSelector.
func (in *ClusterSelector) DeepCopy() *ClusterSelector {
if in == nil {
return nil
}
out := new(ClusterSelector)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FederatedWorkspace) DeepCopyInto(out *FederatedWorkspace) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederatedWorkspace.
func (in *FederatedWorkspace) DeepCopy() *FederatedWorkspace {
if in == nil {
return nil
}
out := new(FederatedWorkspace)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Override) DeepCopyInto(out *Override) {
*out = *in
if in.ClusterOverrides != nil {
in, out := &in.ClusterOverrides, &out.ClusterOverrides
*out = make([]ClusterOverride, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Override.
func (in *Override) DeepCopy() *Override {
if in == nil {
return nil
}
out := new(Override)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Placement) DeepCopyInto(out *Placement) {
*out = *in
if in.Clusters != nil {
in, out := &in.Clusters, &out.Clusters
*out = make([]Cluster, len(*in))
copy(*out, *in)
}
if in.ClusterSelector != nil {
in, out := &in.ClusterSelector, &out.ClusterSelector
*out = new(ClusterSelector)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Placement.
func (in *Placement) DeepCopy() *Placement {
if in == nil {
return nil
}
out := new(Placement)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Template) DeepCopyInto(out *Template) {
*out = *in
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Template.
func (in *Template) DeepCopy() *Template {
if in == nil {
return nil
}
out := new(Template)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WorkspaceTemplate) DeepCopyInto(out *WorkspaceTemplate) {
*out = *in
......@@ -225,28 +83,3 @@ func (in *WorkspaceTemplateList) DeepCopyObject() runtime.Object {
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WorkspaceTemplateSpec) DeepCopyInto(out *WorkspaceTemplateSpec) {
*out = *in
in.Template.DeepCopyInto(&out.Template)
in.Placement.DeepCopyInto(&out.Placement)
if in.Overrides != nil {
in, out := &in.Overrides, &out.Overrides
*out = make([]Override, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceTemplateSpec.
func (in *WorkspaceTemplateSpec) DeepCopy() *WorkspaceTemplateSpec {
if in == nil {
return nil
}
out := new(WorkspaceTemplateSpec)
in.DeepCopyInto(out)
return out
}
......@@ -13,6 +13,8 @@ const (
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +genclient:nonNamespaced
// +k8s:openapi-gen=true
type FederatedWorkspace struct {
metav1.TypeMeta `json:",inline"`
......@@ -29,7 +31,8 @@ type FederatedWorkspaceSpec struct {
}
type WorkspaceTemplate struct {
Spec workspacev1alpha1.WorkspaceSpec `json:"spec,omitempty"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec workspacev1alpha1.WorkspaceSpec `json:"spec,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
......
......@@ -2039,6 +2039,7 @@ func (in *UserTemplate) DeepCopy() *UserTemplate {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WorkspaceTemplate) DeepCopyInto(out *WorkspaceTemplate) {
*out = *in
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
return
}
......
......@@ -31,7 +31,6 @@ import (
// FakeFederatedWorkspaces implements FederatedWorkspaceInterface
type FakeFederatedWorkspaces struct {
Fake *FakeTypesV1beta1
ns string
}
var federatedworkspacesResource = schema.GroupVersionResource{Group: "types.kubefed.io", Version: "v1beta1", Resource: "federatedworkspaces"}
......@@ -41,8 +40,7 @@ var federatedworkspacesKind = schema.GroupVersionKind{Group: "types.kubefed.io",
// Get takes name of the federatedWorkspace, and returns the corresponding federatedWorkspace object, and an error if there is any.
func (c *FakeFederatedWorkspaces) Get(name string, options v1.GetOptions) (result *v1beta1.FederatedWorkspace, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(federatedworkspacesResource, c.ns, name), &v1beta1.FederatedWorkspace{})
Invokes(testing.NewRootGetAction(federatedworkspacesResource, name), &v1beta1.FederatedWorkspace{})
if obj == nil {
return nil, err
}
......@@ -52,8 +50,7 @@ func (c *FakeFederatedWorkspaces) Get(name string, options v1.GetOptions) (resul
// List takes label and field selectors, and returns the list of FederatedWorkspaces that match those selectors.
func (c *FakeFederatedWorkspaces) List(opts v1.ListOptions) (result *v1beta1.FederatedWorkspaceList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(federatedworkspacesResource, federatedworkspacesKind, c.ns, opts), &v1beta1.FederatedWorkspaceList{})
Invokes(testing.NewRootListAction(federatedworkspacesResource, federatedworkspacesKind, opts), &v1beta1.FederatedWorkspaceList{})
if obj == nil {
return nil, err
}
......@@ -74,15 +71,13 @@ func (c *FakeFederatedWorkspaces) List(opts v1.ListOptions) (result *v1beta1.Fed
// Watch returns a watch.Interface that watches the requested federatedWorkspaces.
func (c *FakeFederatedWorkspaces) Watch(opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(federatedworkspacesResource, c.ns, opts))
InvokesWatch(testing.NewRootWatchAction(federatedworkspacesResource, opts))
}
// Create takes the representation of a federatedWorkspace and creates it. Returns the server's representation of the federatedWorkspace, and an error, if there is any.
func (c *FakeFederatedWorkspaces) Create(federatedWorkspace *v1beta1.FederatedWorkspace) (result *v1beta1.FederatedWorkspace, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(federatedworkspacesResource, c.ns, federatedWorkspace), &v1beta1.FederatedWorkspace{})
Invokes(testing.NewRootCreateAction(federatedworkspacesResource, federatedWorkspace), &v1beta1.FederatedWorkspace{})
if obj == nil {
return nil, err
}
......@@ -92,8 +87,7 @@ func (c *FakeFederatedWorkspaces) Create(federatedWorkspace *v1beta1.FederatedWo
// Update takes the representation of a federatedWorkspace and updates it. Returns the server's representation of the federatedWorkspace, and an error, if there is any.
func (c *FakeFederatedWorkspaces) Update(federatedWorkspace *v1beta1.FederatedWorkspace) (result *v1beta1.FederatedWorkspace, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(federatedworkspacesResource, c.ns, federatedWorkspace), &v1beta1.FederatedWorkspace{})
Invokes(testing.NewRootUpdateAction(federatedworkspacesResource, federatedWorkspace), &v1beta1.FederatedWorkspace{})
if obj == nil {
return nil, err
}
......@@ -104,8 +98,7 @@ func (c *FakeFederatedWorkspaces) Update(federatedWorkspace *v1beta1.FederatedWo
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *FakeFederatedWorkspaces) UpdateStatus(federatedWorkspace *v1beta1.FederatedWorkspace) (*v1beta1.FederatedWorkspace, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(federatedworkspacesResource, "status", c.ns, federatedWorkspace), &v1beta1.FederatedWorkspace{})
Invokes(testing.NewRootUpdateSubresourceAction(federatedworkspacesResource, "status", federatedWorkspace), &v1beta1.FederatedWorkspace{})
if obj == nil {
return nil, err
}
......@@ -115,14 +108,13 @@ func (c *FakeFederatedWorkspaces) UpdateStatus(federatedWorkspace *v1beta1.Feder
// Delete takes name of the federatedWorkspace and deletes it. Returns an error if one occurs.
func (c *FakeFederatedWorkspaces) Delete(name string, options *v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(federatedworkspacesResource, c.ns, name), &v1beta1.FederatedWorkspace{})
Invokes(testing.NewRootDeleteAction(federatedworkspacesResource, name), &v1beta1.FederatedWorkspace{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeFederatedWorkspaces) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(federatedworkspacesResource, c.ns, listOptions)
action := testing.NewRootDeleteCollectionAction(federatedworkspacesResource, listOptions)
_, err := c.Fake.Invokes(action, &v1beta1.FederatedWorkspaceList{})
return err
......@@ -131,8 +123,7 @@ func (c *FakeFederatedWorkspaces) DeleteCollection(options *v1.DeleteOptions, li
// Patch applies the patch and returns the patched federatedWorkspace.
func (c *FakeFederatedWorkspaces) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.FederatedWorkspace, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(federatedworkspacesResource, c.ns, name, pt, data, subresources...), &v1beta1.FederatedWorkspace{})
Invokes(testing.NewRootPatchSubresourceAction(federatedworkspacesResource, name, pt, data, subresources...), &v1beta1.FederatedWorkspace{})
if obj == nil {
return nil, err
}
......
......@@ -88,8 +88,8 @@ func (c *FakeTypesV1beta1) FederatedUsers(namespace string) v1beta1.FederatedUse
return &FakeFederatedUsers{c, namespace}
}
func (c *FakeTypesV1beta1) FederatedWorkspaces(namespace string) v1beta1.FederatedWorkspaceInterface {
return &FakeFederatedWorkspaces{c, namespace}
func (c *FakeTypesV1beta1) FederatedWorkspaces() v1beta1.FederatedWorkspaceInterface {
return &FakeFederatedWorkspaces{c}
}
// RESTClient returns a RESTClient that is used to communicate
......
......@@ -32,7 +32,7 @@ import (
// FederatedWorkspacesGetter has a method to return a FederatedWorkspaceInterface.
// A group's client should implement this interface.
type FederatedWorkspacesGetter interface {
FederatedWorkspaces(namespace string) FederatedWorkspaceInterface
FederatedWorkspaces() FederatedWorkspaceInterface
}
// FederatedWorkspaceInterface has methods to work with FederatedWorkspace resources.
......@@ -52,14 +52,12 @@ type FederatedWorkspaceInterface interface {
// federatedWorkspaces implements FederatedWorkspaceInterface
type federatedWorkspaces struct {
client rest.Interface
ns string
}
// newFederatedWorkspaces returns a FederatedWorkspaces
func newFederatedWorkspaces(c *TypesV1beta1Client, namespace string) *federatedWorkspaces {
func newFederatedWorkspaces(c *TypesV1beta1Client) *federatedWorkspaces {
return &federatedWorkspaces{
client: c.RESTClient(),
ns: namespace,
}
}
......@@ -67,7 +65,6 @@ func newFederatedWorkspaces(c *TypesV1beta1Client, namespace string) *federatedW
func (c *federatedWorkspaces) Get(name string, options v1.GetOptions) (result *v1beta1.FederatedWorkspace, err error) {
result = &v1beta1.FederatedWorkspace{}
err = c.client.Get().
Namespace(c.ns).
Resource("federatedworkspaces").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
......@@ -84,7 +81,6 @@ func (c *federatedWorkspaces) List(opts v1.ListOptions) (result *v1beta1.Federat
}
result = &v1beta1.FederatedWorkspaceList{}
err = c.client.Get().
Namespace(c.ns).
Resource("federatedworkspaces").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
......@@ -101,7 +97,6 @@ func (c *federatedWorkspaces) Watch(opts v1.ListOptions) (watch.Interface, error
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("federatedworkspaces").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
......@@ -112,7 +107,6 @@ func (c *federatedWorkspaces) Watch(opts v1.ListOptions) (watch.Interface, error
func (c *federatedWorkspaces) Create(federatedWorkspace *v1beta1.FederatedWorkspace) (result *v1beta1.FederatedWorkspace, err error) {
result = &v1beta1.FederatedWorkspace{}
err = c.client.Post().
Namespace(c.ns).
Resource("federatedworkspaces").
Body(federatedWorkspace).
Do().
......@@ -124,7 +118,6 @@ func (c *federatedWorkspaces) Create(federatedWorkspace *v1beta1.FederatedWorksp
func (c *federatedWorkspaces) Update(federatedWorkspace *v1beta1.FederatedWorkspace) (result *v1beta1.FederatedWorkspace, err error) {
result = &v1beta1.FederatedWorkspace{}
err = c.client.Put().
Namespace(c.ns).
Resource("federatedworkspaces").
Name(federatedWorkspace.Name).
Body(federatedWorkspace).
......@@ -139,7 +132,6 @@ func (c *federatedWorkspaces) Update(federatedWorkspace *v1beta1.FederatedWorksp
func (c *federatedWorkspaces) UpdateStatus(federatedWorkspace *v1beta1.FederatedWorkspace) (result *v1beta1.FederatedWorkspace, err error) {
result = &v1beta1.FederatedWorkspace{}
err = c.client.Put().
Namespace(c.ns).
Resource("federatedworkspaces").
Name(federatedWorkspace.Name).
SubResource("status").
......@@ -152,7 +144,6 @@ func (c *federatedWorkspaces) UpdateStatus(federatedWorkspace *v1beta1.Federated
// Delete takes name of the federatedWorkspace and deletes it. Returns an error if one occurs.
func (c *federatedWorkspaces) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("federatedworkspaces").
Name(name).
Body(options).
......@@ -167,7 +158,6 @@ func (c *federatedWorkspaces) DeleteCollection(options *v1.DeleteOptions, listOp
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("federatedworkspaces").
VersionedParams(&listOptions, scheme.ParameterCodec).
Timeout(timeout).
......@@ -180,7 +170,6 @@ func (c *federatedWorkspaces) DeleteCollection(options *v1.DeleteOptions, listOp
func (c *federatedWorkspaces) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.FederatedWorkspace, err error) {
result = &v1beta1.FederatedWorkspace{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("federatedworkspaces").
SubResource(subresources...).
Name(name).
......
......@@ -109,8 +109,8 @@ func (c *TypesV1beta1Client) FederatedUsers(namespace string) FederatedUserInter
return newFederatedUsers(c, namespace)
}
func (c *TypesV1beta1Client) FederatedWorkspaces(namespace string) FederatedWorkspaceInterface {
return newFederatedWorkspaces(c, namespace)
func (c *TypesV1beta1Client) FederatedWorkspaces() FederatedWorkspaceInterface {
return newFederatedWorkspaces(c)
}
// NewForConfig creates a new TypesV1beta1Client for the given config.
......
......@@ -41,33 +41,32 @@ type FederatedWorkspaceInformer interface {
type federatedWorkspaceInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewFederatedWorkspaceInformer constructs a new informer for FederatedWorkspace 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 NewFederatedWorkspaceInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredFederatedWorkspaceInformer(client, namespace, resyncPeriod, indexers, nil)
func NewFederatedWorkspaceInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredFederatedWorkspaceInformer(client, resyncPeriod, indexers, nil)
}
// NewFilteredFederatedWorkspaceInformer constructs a new informer for FederatedWorkspace 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 NewFilteredFederatedWorkspaceInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
func NewFilteredFederatedWorkspaceInformer(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().FederatedWorkspaces(namespace).List(options)
return client.TypesV1beta1().FederatedWorkspaces().List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.TypesV1beta1().FederatedWorkspaces(namespace).Watch(options)
return client.TypesV1beta1().FederatedWorkspaces().Watch(options)
},
},
&typesv1beta1.FederatedWorkspace{},
......@@ -77,7 +76,7 @@ func NewFilteredFederatedWorkspaceInformer(client versioned.Interface, namespace
}
func (f *federatedWorkspaceInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredFederatedWorkspaceInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
return NewFilteredFederatedWorkspaceInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *federatedWorkspaceInformer) Informer() cache.SharedIndexInformer {
......
......@@ -146,5 +146,5 @@ func (v *version) FederatedUsers() FederatedUserInformer {
// FederatedWorkspaces returns a FederatedWorkspaceInformer.
func (v *version) FederatedWorkspaces() FederatedWorkspaceInformer {
return &federatedWorkspaceInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
return &federatedWorkspaceInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
}
......@@ -141,7 +141,3 @@ type FederatedUserNamespaceListerExpansion interface{}
// FederatedWorkspaceListerExpansion allows custom methods to be added to
// FederatedWorkspaceLister.
type FederatedWorkspaceListerExpansion interface{}
// FederatedWorkspaceNamespaceListerExpansion allows custom methods to be added to
// FederatedWorkspaceNamespaceLister.
type FederatedWorkspaceNamespaceListerExpansion interface{}
......@@ -29,8 +29,8 @@ import (
type FederatedWorkspaceLister interface {
// List lists all FederatedWorkspaces in the indexer.
List(selector labels.Selector) (ret []*v1beta1.FederatedWorkspace, err error)
// FederatedWorkspaces returns an object that can list and get FederatedWorkspaces.
FederatedWorkspaces(namespace string) FederatedWorkspaceNamespaceLister
// Get retrieves the FederatedWorkspace from the index for a given name.
Get(name string) (*v1beta1.FederatedWorkspace, error)
FederatedWorkspaceListerExpansion
}
......@@ -52,38 +52,9 @@ func (s *federatedWorkspaceLister) List(selector labels.Selector) (ret []*v1beta
return ret, err
}
// FederatedWorkspaces returns an object that can list and get FederatedWorkspaces.
func (s *federatedWorkspaceLister) FederatedWorkspaces(namespace string) FederatedWorkspaceNamespaceLister {
return federatedWorkspaceNamespaceLister{indexer: s.indexer, namespace: namespace}
}
// FederatedWorkspaceNamespaceLister helps list and get FederatedWorkspaces.
type FederatedWorkspaceNamespaceLister interface {
// List lists all FederatedWorkspaces in the indexer for a given namespace.
List(selector labels.Selector) (ret []*v1beta1.FederatedWorkspace, err error)
// Get retrieves the FederatedWorkspace from the indexer for a given namespace and name.
Get(name string) (*v1beta1.FederatedWorkspace, error)
FederatedWorkspaceNamespaceListerExpansion
}
// federatedWorkspaceNamespaceLister implements the FederatedWorkspaceNamespaceLister
// interface.
type federatedWorkspaceNamespaceLister struct {
indexer cache.Indexer
namespace string
}
// List lists all FederatedWorkspaces in the indexer for a given namespace.
func (s federatedWorkspaceNamespaceLister) List(selector labels.Selector) (ret []*v1beta1.FederatedWorkspace, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*v1beta1.FederatedWorkspace))
})
return ret, err
}
// Get retrieves the FederatedWorkspace from the indexer for a given namespace and name.
func (s federatedWorkspaceNamespaceLister) Get(name string) (*v1beta1.FederatedWorkspace, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
// Get retrieves the FederatedWorkspace from the index for a given name.
func (s *federatedWorkspaceLister) Get(name string) (*v1beta1.FederatedWorkspace, error) {
obj, exists, err := s.indexer.GetByKey(name)
if err != nil {
return nil, err
}
......
......@@ -94,11 +94,11 @@ func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface
}
klog.Info("Setting up event handlers")
globalRoleInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: ctl.enqueueClusterRole,
AddFunc: ctl.enqueueGlobalRole,
UpdateFunc: func(old, new interface{}) {
ctl.enqueueClusterRole(new)
ctl.enqueueGlobalRole(new)
},
DeleteFunc: ctl.enqueueClusterRole,
DeleteFunc: ctl.enqueueGlobalRole,
})
return ctl
}
......@@ -129,7 +129,7 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error {
return nil
}
func (c *Controller) enqueueClusterRole(obj interface{}) {
func (c *Controller) enqueueGlobalRole(obj interface{}) {
var key string
var err error
if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil {
......
......@@ -293,14 +293,6 @@ func (r *ReconcileNamespace) initRoles(namespace *corev1.Namespace) error {
return nil
}
func (r *ReconcileNamespace) resetNamespaceOwner(namespace *corev1.Namespace) error {
namespace = namespace.DeepCopy()
delete(namespace.Annotations, constants.CreatorAnnotationKey)
err := r.Update(context.Background(), namespace)
klog.V(4).Infof("update namespace after creator has been deleted")
return err
}
func (r *ReconcileNamespace) initCreatorRoleBinding(namespace *corev1.Namespace) error {
creator := namespace.Annotations[constants.CreatorAnnotationKey]
if creator == "" {
......@@ -308,21 +300,14 @@ func (r *ReconcileNamespace) initCreatorRoleBinding(namespace *corev1.Namespace)
}
var user iamv1alpha2.User
err := r.Get(context.Background(), types.NamespacedName{Name: creator}, &user)
if err != nil {
// skip if user has been deleted
if err := r.Get(context.Background(), types.NamespacedName{Name: creator}, &user); err != nil {
if errors.IsNotFound(err) {
return r.resetNamespaceOwner(namespace)
return nil
}
klog.Error(err)
return err
}
// skip if user has been deleted
if !user.DeletionTimestamp.IsZero() {
return r.resetNamespaceOwner(namespace)
}
creatorRoleBinding := &rbacv1.RoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-%s", creator, iamv1alpha2.NamespaceAdmin),
......@@ -342,8 +327,8 @@ func (r *ReconcileNamespace) initCreatorRoleBinding(namespace *corev1.Namespace)
},
},
}
err = r.Client.Create(context.Background(), creatorRoleBinding)
if err != nil {
if err := r.Client.Create(context.Background(), creatorRoleBinding); err != nil {
if errors.IsAlreadyExists(err) {
return nil
}
......
......@@ -105,11 +105,11 @@ func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface
}
klog.Info("Setting up event handlers")
workspaceRoleInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: ctl.enqueueClusterRole,
AddFunc: ctl.enqueueWorkspaceRole,
UpdateFunc: func(old, new interface{}) {
ctl.enqueueClusterRole(new)
ctl.enqueueWorkspaceRole(new)
},
DeleteFunc: ctl.enqueueClusterRole,
DeleteFunc: ctl.enqueueWorkspaceRole,
})
return ctl
}
......@@ -146,7 +146,7 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error {
return nil
}
func (c *Controller) enqueueClusterRole(obj interface{}) {
func (c *Controller) enqueueWorkspaceRole(obj interface{}) {
var key string
var err error
if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil {
......
......@@ -18,15 +18,12 @@ package workspacetemplate
import (
"bytes"
"encoding/json"
"fmt"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/util/yaml"
......@@ -40,13 +37,16 @@ import (
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
tenantv1alpha2 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha2"
typesv1beta1 "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"
tenantv1alpha1informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/tenant/v1alpha1"
tenantv1alpha2informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/tenant/v1alpha2"
typesv1beta1informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/types/v1beta1"
iamv1alpha2listers "kubesphere.io/kubesphere/pkg/client/listers/iam/v1alpha2"
tenantv1alpha1listers "kubesphere.io/kubesphere/pkg/client/listers/tenant/v1alpha1"
tenantv1alpha2listers "kubesphere.io/kubesphere/pkg/client/listers/tenant/v1alpha2"
typesv1beta1listers "kubesphere.io/kubesphere/pkg/client/listers/types/v1beta1"
"reflect"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"time"
......@@ -61,23 +61,24 @@ const (
)
type Controller struct {
k8sClient kubernetes.Interface
ksClient kubesphere.Interface
workspaceTemplateInformer tenantv1alpha2informers.WorkspaceTemplateInformer
workspaceTemplateLister tenantv1alpha2listers.WorkspaceTemplateLister
workspaceTemplateSynced cache.InformerSynced
workspaceRoleInformer iamv1alpha2informers.WorkspaceRoleInformer
workspaceRoleLister iamv1alpha2listers.WorkspaceRoleLister
workspaceRoleSynced cache.InformerSynced
roleBaseInformer iamv1alpha2informers.RoleBaseInformer
roleBaseLister iamv1alpha2listers.RoleBaseLister
roleBaseSynced cache.InformerSynced
workspaceInformer tenantv1alpha1informers.WorkspaceInformer
workspaceLister tenantv1alpha1listers.WorkspaceLister
workspaceSynced cache.InformerSynced
fedWorkspaceCache cache.Store
fedWorkspaceCacheController cache.Controller
multiClusterEnabled bool
k8sClient kubernetes.Interface
ksClient kubesphere.Interface
workspaceTemplateInformer tenantv1alpha2informers.WorkspaceTemplateInformer
workspaceTemplateLister tenantv1alpha2listers.WorkspaceTemplateLister
workspaceTemplateSynced cache.InformerSynced
workspaceRoleInformer iamv1alpha2informers.WorkspaceRoleInformer
workspaceRoleLister iamv1alpha2listers.WorkspaceRoleLister
workspaceRoleSynced cache.InformerSynced
roleBaseInformer iamv1alpha2informers.RoleBaseInformer
roleBaseLister iamv1alpha2listers.RoleBaseLister
roleBaseSynced cache.InformerSynced
workspaceInformer tenantv1alpha1informers.WorkspaceInformer
workspaceLister tenantv1alpha1listers.WorkspaceLister
workspaceSynced cache.InformerSynced
federatedWorkspaceInformer typesv1beta1informers.FederatedWorkspaceInformer
federatedWorkspaceLister typesv1beta1listers.FederatedWorkspaceLister
federatedWorkspaceSynced cache.InformerSynced
multiClusterEnabled bool
// workqueue is a rate limited work queue. This is used to queue work to be
// processed instead of performing it as soon as a change happens. This
// means we can ensure we only process a fixed amount of resources at a
......@@ -89,9 +90,13 @@ type Controller struct {
recorder record.EventRecorder
}
func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface, workspaceTemplateInformer tenantv1alpha2informers.WorkspaceTemplateInformer,
workspaceInformer tenantv1alpha1informers.WorkspaceInformer, roleBaseInformer iamv1alpha2informers.RoleBaseInformer, workspaceRoleInformer iamv1alpha2informers.WorkspaceRoleInformer,
fedWorkspaceCache cache.Store, fedWorkspaceCacheController cache.Controller, multiClusterEnabled bool) *Controller {
func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface,
workspaceTemplateInformer tenantv1alpha2informers.WorkspaceTemplateInformer,
workspaceInformer tenantv1alpha1informers.WorkspaceInformer,
roleBaseInformer iamv1alpha2informers.RoleBaseInformer,
workspaceRoleInformer iamv1alpha2informers.WorkspaceRoleInformer,
federatedWorkspaceInformer typesv1beta1informers.FederatedWorkspaceInformer,
multiClusterEnabled bool) *Controller {
// Create event broadcaster
// Add sample-controller types to the default Kubernetes Scheme so Events can be
// logged for sample-controller types.
......@@ -102,33 +107,34 @@ func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface
eventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{Interface: k8sClient.CoreV1().Events("")})
recorder := eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: controllerName})
ctl := &Controller{
k8sClient: k8sClient,
ksClient: ksClient,
workspaceTemplateInformer: workspaceTemplateInformer,
workspaceTemplateLister: workspaceTemplateInformer.Lister(),
workspaceTemplateSynced: workspaceTemplateInformer.Informer().HasSynced,
workspaceInformer: workspaceInformer,
workspaceLister: workspaceInformer.Lister(),
workspaceSynced: workspaceInformer.Informer().HasSynced,
workspaceRoleInformer: workspaceRoleInformer,
workspaceRoleLister: workspaceRoleInformer.Lister(),
workspaceRoleSynced: workspaceRoleInformer.Informer().HasSynced,
roleBaseInformer: roleBaseInformer,
roleBaseLister: roleBaseInformer.Lister(),
roleBaseSynced: roleBaseInformer.Informer().HasSynced,
fedWorkspaceCache: fedWorkspaceCache,
fedWorkspaceCacheController: fedWorkspaceCacheController,
multiClusterEnabled: multiClusterEnabled,
workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "WorkspaceTemplate"),
recorder: recorder,
k8sClient: k8sClient,
ksClient: ksClient,
workspaceTemplateInformer: workspaceTemplateInformer,
workspaceTemplateLister: workspaceTemplateInformer.Lister(),
workspaceTemplateSynced: workspaceTemplateInformer.Informer().HasSynced,
workspaceInformer: workspaceInformer,
workspaceLister: workspaceInformer.Lister(),
workspaceSynced: workspaceInformer.Informer().HasSynced,
workspaceRoleInformer: workspaceRoleInformer,
workspaceRoleLister: workspaceRoleInformer.Lister(),
workspaceRoleSynced: workspaceRoleInformer.Informer().HasSynced,
roleBaseInformer: roleBaseInformer,
roleBaseLister: roleBaseInformer.Lister(),
roleBaseSynced: roleBaseInformer.Informer().HasSynced,
federatedWorkspaceInformer: federatedWorkspaceInformer,
federatedWorkspaceLister: federatedWorkspaceInformer.Lister(),
federatedWorkspaceSynced: federatedWorkspaceInformer.Informer().HasSynced,
multiClusterEnabled: multiClusterEnabled,
workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "WorkspaceTemplate"),
recorder: recorder,
}
klog.Info("Setting up event handlers")
workspaceTemplateInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: ctl.enqueueClusterRole,
AddFunc: ctl.enqueueWorkspaceTemplate,
UpdateFunc: func(old, new interface{}) {
ctl.enqueueClusterRole(new)
ctl.enqueueWorkspaceTemplate(new)
},
DeleteFunc: ctl.enqueueClusterRole,
DeleteFunc: ctl.enqueueWorkspaceTemplate,
})
return ctl
}
......@@ -146,7 +152,7 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error {
synced := make([]cache.InformerSynced, 0)
synced = append(synced, c.workspaceTemplateSynced, c.workspaceSynced, c.workspaceRoleSynced, c.roleBaseSynced)
if c.multiClusterEnabled {
synced = append(synced, c.fedWorkspaceCacheController.HasSynced)
synced = append(synced, c.federatedWorkspaceSynced)
}
if ok := cache.WaitForCacheSync(stopCh, synced...); !ok {
return fmt.Errorf("failed to wait for caches to sync")
......@@ -164,7 +170,7 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error {
return nil
}
func (c *Controller) enqueueClusterRole(obj interface{}) {
func (c *Controller) enqueueWorkspaceTemplate(obj interface{}) {
var key string
var err error
if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil {
......@@ -236,7 +242,6 @@ func (c *Controller) processNextWorkItem() bool {
// converge the two. It then updates the Status block of the Foo resource
// with the current status of the resource.
func (c *Controller) reconcile(key string) error {
workspaceTemplate, err := c.workspaceTemplateLister.Get(key)
if err != nil {
// The user may no longer exist, in which case we stop
......@@ -280,91 +285,45 @@ func (c *Controller) Start(stopCh <-chan struct{}) error {
}
func (c *Controller) multiClusterSync(workspaceTemplate *tenantv1alpha2.WorkspaceTemplate) error {
obj, exist, err := c.fedWorkspaceCache.GetByKey(workspaceTemplate.Name)
if !exist {
return c.createFederatedWorkspace(workspaceTemplate)
}
// multi cluster environment, synchronize workspaces with kubefed
federatedWorkspace, err := c.federatedWorkspaceLister.Get(workspaceTemplate.Name)
if err != nil {
// create federatedworkspace if not found
if errors.IsNotFound(err) {
return c.createFederatedWorkspace(workspaceTemplate)
}
klog.Error(err)
return err
}
var fedWorkspace tenantv1alpha2.FederatedWorkspace
if err = runtime.DefaultUnstructuredConverter.FromUnstructured(obj.(*unstructured.Unstructured).Object, &fedWorkspace); err != nil {
klog.Error(err)
return err
}
if !reflect.DeepEqual(fedWorkspace.Spec, workspaceTemplate.Spec) {
fedWorkspace.Spec = workspaceTemplate.Spec
return c.updateFederatedWorkspace(&fedWorkspace)
// update spec
if !reflect.DeepEqual(federatedWorkspace.Spec, workspaceTemplate.Spec) {
federatedWorkspace.Spec = workspaceTemplate.Spec
if err := c.updateFederatedWorkspace(federatedWorkspace); err != nil {
klog.Error(err)
return err
}
}
return nil
}
func (c *Controller) createFederatedWorkspace(workspaceTemplate *tenantv1alpha2.WorkspaceTemplate) error {
federatedWorkspace := &tenantv1alpha2.FederatedWorkspace{
TypeMeta: metav1.TypeMeta{
Kind: tenantv1alpha2.FedWorkspaceKind,
APIVersion: tenantv1alpha2.FedWorkspaceResource.Group + "/" + tenantv1alpha2.FedWorkspaceResource.Version,
},
federatedWorkspace := &typesv1beta1.FederatedWorkspace{
ObjectMeta: metav1.ObjectMeta{
Name: workspaceTemplate.Name,
},
Spec: workspaceTemplate.Spec,
}
err := controllerutil.SetControllerReference(workspaceTemplate, federatedWorkspace, scheme.Scheme)
if err != nil {
return err
}
data, err := json.Marshal(federatedWorkspace)
if err != nil {
if err := controllerutil.SetControllerReference(workspaceTemplate, federatedWorkspace, scheme.Scheme); err != nil {
return err
}
cli := c.k8sClient.(*kubernetes.Clientset)
err = cli.RESTClient().Post().
AbsPath(fmt.Sprintf("/apis/%s/%s/%s", tenantv1alpha2.FedWorkspaceResource.Group,
tenantv1alpha2.FedWorkspaceResource.Version, tenantv1alpha2.FedWorkspaceResource.Name)).
Body(data).
Do().Error()
if err != nil {
if _, err := c.ksClient.TypesV1beta1().FederatedWorkspaces().Create(federatedWorkspace); err != nil {
if errors.IsAlreadyExists(err) {
return nil
}
return err
}
return nil
}
func (c *Controller) updateFederatedWorkspace(fedWorkspace *tenantv1alpha2.FederatedWorkspace) error {
data, err := json.Marshal(fedWorkspace)
if err != nil {
return err
}
cli := c.k8sClient.(*kubernetes.Clientset)
err = cli.RESTClient().Put().
AbsPath(fmt.Sprintf("/apis/%s/%s/%s/%s", tenantv1alpha2.FedWorkspaceResource.Group,
tenantv1alpha2.FedWorkspaceResource.Version, tenantv1alpha2.FedWorkspaceResource.Name,
fedWorkspace.Name)).
Body(data).
Do().Error()
if err != nil {
if errors.IsNotFound(err) {
return nil
}
klog.Error(err)
return err
}
......@@ -539,3 +498,12 @@ func (r *Controller) initManagerRoleBinding(workspace *tenantv1alpha2.WorkspaceT
return nil
}
func (c *Controller) updateFederatedWorkspace(workspace *typesv1beta1.FederatedWorkspace) error {
_, err := c.ksClient.TypesV1beta1().FederatedWorkspaces().Update(workspace)
if err != nil {
klog.Error(err)
return err
}
return nil
}
package v1alpha2
import (
"encoding/json"
"fmt"
"github.com/emicklei/go-restful"
corev1 "k8s.io/api/core/v1"
......@@ -476,18 +477,15 @@ func (h *tenantHandler) PatchNamespace(request *restful.Request, response *restf
func (h *tenantHandler) PatchWorkspace(request *restful.Request, response *restful.Response) {
workspaceName := request.PathParameter("workspace")
var workspace tenantv1alpha2.WorkspaceTemplate
err := request.ReadEntity(&workspace)
var data json.RawMessage
err := request.ReadEntity(&data)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
workspace.Name = workspaceName
patched, err := h.tenant.PatchWorkspace(&workspace)
patched, err := h.tenant.PatchWorkspace(workspaceName, data)
if err != nil {
klog.Error(err)
......
......@@ -76,7 +76,7 @@ type Interface interface {
DeleteNamespace(workspace, namespace string) error
UpdateNamespace(workspace string, namespace *corev1.Namespace) (*corev1.Namespace, error)
PatchNamespace(workspace string, namespace *corev1.Namespace) (*corev1.Namespace, error)
PatchWorkspace(workspace *tenantv1alpha2.WorkspaceTemplate) (*tenantv1alpha2.WorkspaceTemplate, error)
PatchWorkspace(workspace string, data json.RawMessage) (*tenantv1alpha2.WorkspaceTemplate, error)
ListClusters(info user.Info) (*api.ListResult, error)
}
......@@ -369,16 +369,8 @@ func (t *tenantOperator) PatchNamespace(workspace string, namespace *corev1.Name
return t.k8sclient.CoreV1().Namespaces().Patch(namespace.Name, types.MergePatchType, data)
}
func (t *tenantOperator) PatchWorkspace(workspace *tenantv1alpha2.WorkspaceTemplate) (*tenantv1alpha2.WorkspaceTemplate, error) {
_, err := t.DescribeWorkspace(workspace.Name)
if err != nil {
return nil, err
}
data, err := json.Marshal(workspace)
if err != nil {
return nil, err
}
return t.ksclient.TenantV1alpha2().WorkspaceTemplates().Patch(workspace.Name, types.MergePatchType, data)
func (t *tenantOperator) PatchWorkspace(workspace string, data json.RawMessage) (*tenantv1alpha2.WorkspaceTemplate, error) {
return t.ksclient.TenantV1alpha2().WorkspaceTemplates().Patch(workspace, types.MergePatchType, data)
}
func (t *tenantOperator) CreateWorkspace(workspace *tenantv1alpha2.WorkspaceTemplate) (*tenantv1alpha2.WorkspaceTemplate, error) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册