@@ -17,13 +17,138 @@ limitations under the License.
1717package multicluster
1818
1919import (
20+ "context"
2021 "os"
2122
2223 clustergatewayv1alpha1 "github.com/oam-dev/cluster-gateway/pkg/apis/cluster/v1alpha1"
24+ "k8s.io/apimachinery/pkg/api/meta"
25+ "k8s.io/apimachinery/pkg/runtime"
2326 "k8s.io/client-go/rest"
2427 "sigs.k8s.io/controller-runtime/pkg/client"
2528)
2629
30+ // gatedClient use base client to handle hub cluster requests and
31+ // use gateway client to do managed cluster requests
32+ type gatedClient struct {
33+ base client.Client
34+ gateway client.Client
35+ writer * gatedStatusWriter
36+ }
37+
38+ // gatedStatusWriter use base writer to handle hub cluster requests and
39+ // use gateway writer to do managed cluster requests
40+ type gatedStatusWriter struct {
41+ base client.StatusWriter
42+ gateway client.StatusWriter
43+ }
44+
45+ // gatedSubResourceClient use base client to handle hub cluster requests and
46+ // use gateway client to do managed cluster requests
47+ type gatedSubResourceClient struct {
48+ base client.SubResourceClient
49+ gateway client.SubResourceClient
50+ }
51+
52+ var _ client.Client = & gatedClient {}
53+ var _ client.StatusWriter = & gatedStatusWriter {}
54+ var _ client.SubResourceClient = & gatedSubResourceClient {}
55+
56+ func (m * gatedClient ) getClientFor (ctx context.Context ) client.Client {
57+ if cluster , exists := ClusterFrom (ctx ); ! exists || IsLocal (cluster ) {
58+ return m .base
59+ }
60+ return m .gateway
61+ }
62+
63+ func (m * gatedStatusWriter ) getWriterFor (ctx context.Context ) client.StatusWriter {
64+ if cluster , exists := ClusterFrom (ctx ); ! exists || IsLocal (cluster ) {
65+ return m .base
66+ }
67+ return m .gateway
68+ }
69+
70+ func (m * gatedSubResourceClient ) getClientFor (ctx context.Context ) client.SubResourceClient {
71+ if cluster , exists := ClusterFrom (ctx ); ! exists || IsLocal (cluster ) {
72+ return m .base
73+ }
74+ return m .gateway
75+ }
76+
77+ func (m * gatedClient ) Get (ctx context.Context , key client.ObjectKey , obj client.Object , opts ... client.GetOption ) error {
78+ return m .getClientFor (ctx ).Get (ctx , key , obj , opts ... )
79+ }
80+
81+ func (m * gatedClient ) List (ctx context.Context , list client.ObjectList , opts ... client.ListOption ) error {
82+ return m .getClientFor (ctx ).List (ctx , list , opts ... )
83+ }
84+
85+ func (m * gatedClient ) Create (ctx context.Context , obj client.Object , opts ... client.CreateOption ) error {
86+ return m .getClientFor (ctx ).Create (ctx , obj , opts ... )
87+ }
88+
89+ func (m * gatedClient ) Delete (ctx context.Context , obj client.Object , opts ... client.DeleteOption ) error {
90+ return m .getClientFor (ctx ).Delete (ctx , obj , opts ... )
91+ }
92+
93+ func (m * gatedClient ) Update (ctx context.Context , obj client.Object , opts ... client.UpdateOption ) error {
94+ return m .getClientFor (ctx ).Update (ctx , obj , opts ... )
95+ }
96+
97+ func (m * gatedClient ) Patch (ctx context.Context , obj client.Object , patch client.Patch , opts ... client.PatchOption ) error {
98+ return m .getClientFor (ctx ).Patch (ctx , obj , patch , opts ... )
99+ }
100+
101+ func (m * gatedClient ) DeleteAllOf (ctx context.Context , obj client.Object , opts ... client.DeleteAllOfOption ) error {
102+ return m .getClientFor (ctx ).DeleteAllOf (ctx , obj , opts ... )
103+ }
104+
105+ func (m * gatedClient ) SubResource (subResource string ) client.SubResourceClient {
106+ return & gatedSubResourceClient {
107+ base : m .base .SubResource (subResource ),
108+ gateway : m .gateway .SubResource (subResource ),
109+ }
110+ }
111+
112+ func (m * gatedClient ) Status () client.StatusWriter {
113+ return m .writer
114+ }
115+
116+ func (m * gatedClient ) Scheme () * runtime.Scheme {
117+ return m .base .Scheme ()
118+ }
119+
120+ func (m * gatedClient ) RESTMapper () meta.RESTMapper {
121+ return m .base .RESTMapper ()
122+ }
123+
124+ func (m * gatedStatusWriter ) Create (ctx context.Context , obj client.Object , subResource client.Object , opts ... client.SubResourceCreateOption ) error {
125+ return m .getWriterFor (ctx ).Create (ctx , obj , subResource , opts ... )
126+ }
127+
128+ func (m * gatedStatusWriter ) Update (ctx context.Context , obj client.Object , opts ... client.SubResourceUpdateOption ) error {
129+ return m .getWriterFor (ctx ).Update (ctx , obj , opts ... )
130+ }
131+
132+ func (m * gatedStatusWriter ) Patch (ctx context.Context , obj client.Object , patch client.Patch , opts ... client.SubResourcePatchOption ) error {
133+ return m .getWriterFor (ctx ).Patch (ctx , obj , patch , opts ... )
134+ }
135+
136+ func (m * gatedSubResourceClient ) Get (ctx context.Context , obj client.Object , subResource client.Object , opts ... client.SubResourceGetOption ) error {
137+ return m .getClientFor (ctx ).Get (ctx , obj , subResource , opts ... )
138+ }
139+
140+ func (m * gatedSubResourceClient ) Create (ctx context.Context , obj client.Object , subResource client.Object , opts ... client.SubResourceCreateOption ) error {
141+ return m .getClientFor (ctx ).Create (ctx , obj , subResource , opts ... )
142+ }
143+
144+ func (m * gatedSubResourceClient ) Update (ctx context.Context , obj client.Object , opts ... client.SubResourceUpdateOption ) error {
145+ return m .getClientFor (ctx ).Update (ctx , obj , opts ... )
146+ }
147+
148+ func (m * gatedSubResourceClient ) Patch (ctx context.Context , obj client.Object , patch client.Patch , opts ... client.SubResourcePatchOption ) error {
149+ return m .getClientFor (ctx ).Patch (ctx , obj , patch , opts ... )
150+ }
151+
27152// ClientOptions the options for creating multi-cluster gatedClient
28153type ClientOptions struct {
29154 client.Options
@@ -60,7 +185,10 @@ func NewClient(config *rest.Config, options ClientOptions) (client.Client, error
60185 if len (options .ClusterGateway .URL ) == 0 {
61186 return constructor (wrapped , options .Options )
62187 }
63- var err error
188+ base , err := constructor (config , options .Options )
189+ if err != nil {
190+ return nil , err
191+ }
64192 wrapped .Host = options .ClusterGateway .URL
65193 if len (options .ClusterGateway .CAFile ) > 0 {
66194 if wrapped .CAData , err = os .ReadFile (options .ClusterGateway .CAFile ); err != nil {
@@ -74,7 +202,18 @@ func NewClient(config *rest.Config, options ClientOptions) (client.Client, error
74202 // no err will be returned here
75203 _ = clustergatewayv1alpha1 .AddToScheme (options .Options .Scheme )
76204 }
77- return constructor (wrapped , options .Options )
205+ gateway , err := constructor (wrapped , options .Options )
206+ if err != nil {
207+ return nil , err
208+ }
209+ return & gatedClient {
210+ base : base ,
211+ gateway : gateway ,
212+ writer : & gatedStatusWriter {
213+ base : base .Status (),
214+ gateway : gateway .Status (),
215+ },
216+ }, nil
78217}
79218
80219// DefaultClusterGatewayClientOptions the default ClusterGatewayClientOptions
0 commit comments