提交 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,6 +31,7 @@ type FederatedWorkspaceSpec struct {
}
type WorkspaceTemplate struct {
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec workspacev1alpha1.WorkspaceSpec `json:"spec,omitempty"`
}
......
......@@ -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"
......@@ -75,8 +75,9 @@ type Controller struct {
workspaceInformer tenantv1alpha1informers.WorkspaceInformer
workspaceLister tenantv1alpha1listers.WorkspaceLister
workspaceSynced cache.InformerSynced
fedWorkspaceCache cache.Store
fedWorkspaceCacheController cache.Controller
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
......@@ -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.
......@@ -116,19 +121,20 @@ func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface
roleBaseInformer: roleBaseInformer,
roleBaseLister: roleBaseInformer.Lister(),
roleBaseSynced: roleBaseInformer.Informer().HasSynced,
fedWorkspaceCache: fedWorkspaceCache,
fedWorkspaceCacheController: fedWorkspaceCacheController,
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 {
// 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)
}
if err != nil {
klog.Error(err)
return err
}
var fedWorkspace tenantv1alpha2.FederatedWorkspace
if err = runtime.DefaultUnstructuredConverter.FromUnstructured(obj.(*unstructured.Unstructured).Object, &fedWorkspace); err != nil {
// 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
}
if !reflect.DeepEqual(fedWorkspace.Spec, workspaceTemplate.Spec) {
fedWorkspace.Spec = workspaceTemplate.Spec
return c.updateFederatedWorkspace(&fedWorkspace)
}
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.
先完成此消息的编辑!
想要评论请 注册