github.com/cs3org/reva/v2@v2.27.7/pkg/rgrpc/todo/pool/selector.go (about) 1 // Copyright 2018-2021 CERN 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // In applying this license, CERN does not waive the privileges and immunities 16 // granted to it by virtue of its status as an Intergovernmental Organization 17 // or submit itself to any jurisdiction. 18 19 package pool 20 21 import ( 22 "fmt" 23 "strings" 24 "sync" 25 26 appProvider "github.com/cs3org/go-cs3apis/cs3/app/provider/v1beta1" 27 appRegistry "github.com/cs3org/go-cs3apis/cs3/app/registry/v1beta1" 28 authApplication "github.com/cs3org/go-cs3apis/cs3/auth/applications/v1beta1" 29 authProvider "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1" 30 authRegistry "github.com/cs3org/go-cs3apis/cs3/auth/registry/v1beta1" 31 gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" 32 identityGroup "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1" 33 identityUser "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 34 ocmCore "github.com/cs3org/go-cs3apis/cs3/ocm/core/v1beta1" 35 ocmInvite "github.com/cs3org/go-cs3apis/cs3/ocm/invite/v1beta1" 36 ocmProvider "github.com/cs3org/go-cs3apis/cs3/ocm/provider/v1beta1" 37 permissions "github.com/cs3org/go-cs3apis/cs3/permissions/v1beta1" 38 preferences "github.com/cs3org/go-cs3apis/cs3/preferences/v1beta1" 39 sharingCollaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" 40 sharingLink "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" 41 sharingOCM "github.com/cs3org/go-cs3apis/cs3/sharing/ocm/v1beta1" 42 storageProvider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 43 storageRegistry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" 44 tx "github.com/cs3org/go-cs3apis/cs3/tx/v1beta1" 45 "github.com/cs3org/reva/v2/pkg/registry" 46 "github.com/pkg/errors" 47 "github.com/sercand/kuberesolver/v5" 48 "google.golang.org/grpc" 49 ) 50 51 func init() { 52 // grpc go resolver.Register must only be called during initialization time (i.e. in 53 // an init() function), and is not thread-safe. 54 kuberesolver.RegisterInCluster() 55 } 56 57 type Selectable[T any] interface { 58 Next(opts ...Option) (T, error) 59 } 60 61 var selectors sync.Map 62 63 // RemoveSelector removes given id from the selectors map. 64 func RemoveSelector(id string) { 65 selectors.Delete(id) 66 } 67 68 func GetSelector[T any](k string, id string, f func(cc grpc.ClientConnInterface) T, options ...Option) *Selector[T] { 69 existingSelector, ok := selectors.Load(k + id) 70 if ok { 71 return existingSelector.(*Selector[T]) 72 } 73 74 newSelector := &Selector[T]{ 75 id: id, 76 clientFactory: f, 77 options: options, 78 } 79 80 selectors.Store(k+id, newSelector) 81 82 return newSelector 83 } 84 85 type Selector[T any] struct { 86 id string 87 clientFactory func(cc grpc.ClientConnInterface) T 88 clientMap sync.Map 89 options []Option 90 } 91 92 func (s *Selector[T]) Next(opts ...Option) (T, error) { 93 options := ClientOptions{ 94 registry: registry.GetRegistry(), 95 } 96 97 allOpts := append([]Option{}, s.options...) 98 allOpts = append(allOpts, opts...) 99 100 for _, opt := range allOpts { 101 opt(&options) 102 } 103 104 target := s.id 105 // if the target is given as a recognized gRPC URI, skip registry lookup 106 // see https://github.com/grpc/grpc/blob/master/doc/naming.md#name-syntax 107 prefix := strings.SplitN(s.id, ":", 2)[0] 108 switch { 109 case prefix == "dns": 110 fallthrough 111 case prefix == "unix": 112 fallthrough 113 case prefix == "kubernetes": 114 // use target as is and skip registry lookup 115 case options.registry != nil: 116 // use service registry to look up address 117 services, err := options.registry.GetService(s.id) 118 if err != nil { 119 return *new(T), fmt.Errorf("%s: %w", s.id, err) 120 } 121 122 nodeAddress, err := registry.GetNodeAddress(services) 123 if err != nil { 124 return *new(T), fmt.Errorf("%s: %w", s.id, err) 125 } 126 target = nodeAddress 127 default: 128 // if no registry is available, use the target as is 129 } 130 131 existingClient, ok := s.clientMap.Load(target) 132 if ok { 133 return existingClient.(T), nil 134 } 135 136 conn, err := NewConn(target, allOpts...) 137 if err != nil { 138 return *new(T), errors.Wrap(err, fmt.Sprintf("could not create connection for %s to %s", s.id, target)) 139 } 140 141 newClient := s.clientFactory(conn) 142 s.clientMap.Store(target, newClient) 143 144 return newClient, nil 145 } 146 147 // GatewaySelector returns a Selector[gateway.GatewayAPIClient]. 148 func GatewaySelector(id string, options ...Option) (*Selector[gateway.GatewayAPIClient], error) { 149 return GetSelector[gateway.GatewayAPIClient]( 150 "GatewaySelector", 151 id, 152 gateway.NewGatewayAPIClient, 153 options..., 154 ), nil 155 } 156 157 // IdentityUserSelector returns a Selector[identityUser.UserAPIClient]. 158 func IdentityUserSelector(id string, options ...Option) (*Selector[identityUser.UserAPIClient], error) { 159 return GetSelector[identityUser.UserAPIClient]( 160 "IdentityUserSelector", 161 id, 162 identityUser.NewUserAPIClient, 163 options..., 164 ), nil 165 } 166 167 // IdentityGroupSelector returns a Selector[identityGroup.GroupAPIClient]. 168 func IdentityGroupSelector(id string, options ...Option) (*Selector[identityGroup.GroupAPIClient], error) { 169 return GetSelector[identityGroup.GroupAPIClient]( 170 "IdentityGroupSelector", 171 id, 172 identityGroup.NewGroupAPIClient, 173 options..., 174 ), nil 175 } 176 177 // StorageProviderSelector returns a Selector[storageProvider.ProviderAPIClient]. 178 func StorageProviderSelector(id string, options ...Option) (*Selector[storageProvider.ProviderAPIClient], error) { 179 return GetSelector[storageProvider.ProviderAPIClient]( 180 "StorageProviderSelector", 181 id, 182 storageProvider.NewProviderAPIClient, 183 options..., 184 ), nil 185 } 186 187 // SpacesProviderSelector returns a Selector[storageProvider.SpacesAPIClient]. 188 func SpacesProviderSelector(id string, options ...Option) (*Selector[storageProvider.SpacesAPIClient], error) { 189 return GetSelector[storageProvider.SpacesAPIClient]( 190 "SpacesProviderSelector", 191 id, 192 storageProvider.NewSpacesAPIClient, 193 options..., 194 ), nil 195 } 196 197 // AuthRegistrySelector returns a Selector[authRegistry.RegistryAPIClient]. 198 func AuthRegistrySelector(id string, options ...Option) (*Selector[authRegistry.RegistryAPIClient], error) { 199 return GetSelector[authRegistry.RegistryAPIClient]( 200 "AuthRegistrySelector", 201 id, 202 authRegistry.NewRegistryAPIClient, 203 options..., 204 ), nil 205 } 206 207 // AuthProviderSelector returns a Selector[authProvider.RegistryAPIClient]. 208 func AuthProviderSelector(id string, options ...Option) (*Selector[authProvider.ProviderAPIClient], error) { 209 return GetSelector[authProvider.ProviderAPIClient]( 210 "AuthProviderSelector", 211 id, 212 authProvider.NewProviderAPIClient, 213 options..., 214 ), nil 215 } 216 217 // AuthApplicationSelector returns a Selector[authApplication.ApplicationsAPIClient]. 218 func AuthApplicationSelector(id string, options ...Option) (*Selector[authApplication.ApplicationsAPIClient], error) { 219 return GetSelector[authApplication.ApplicationsAPIClient]( 220 "AuthApplicationSelector", 221 id, 222 authApplication.NewApplicationsAPIClient, 223 options..., 224 ), nil 225 } 226 227 // SharingCollaborationSelector returns a Selector[sharingCollaboration.ApplicationsAPIClient]. 228 func SharingCollaborationSelector(id string, options ...Option) (*Selector[sharingCollaboration.CollaborationAPIClient], error) { 229 return GetSelector[sharingCollaboration.CollaborationAPIClient]( 230 "SharingCollaborationSelector", 231 id, 232 sharingCollaboration.NewCollaborationAPIClient, 233 options..., 234 ), nil 235 } 236 237 // SharingOCMSelector returns a Selector[sharingOCM.OcmAPIClient]. 238 func SharingOCMSelector(id string, options ...Option) (*Selector[sharingOCM.OcmAPIClient], error) { 239 return GetSelector[sharingOCM.OcmAPIClient]( 240 "SharingOCMSelector", 241 id, 242 sharingOCM.NewOcmAPIClient, 243 options..., 244 ), nil 245 } 246 247 // SharingLinkSelector returns a Selector[sharingLink.LinkAPIClient]. 248 func SharingLinkSelector(id string, options ...Option) (*Selector[sharingLink.LinkAPIClient], error) { 249 return GetSelector[sharingLink.LinkAPIClient]( 250 "SharingLinkSelector", 251 id, 252 sharingLink.NewLinkAPIClient, 253 options..., 254 ), nil 255 } 256 257 // PreferencesSelector returns a Selector[preferences.PreferencesAPIClient]. 258 func PreferencesSelector(id string, options ...Option) (*Selector[preferences.PreferencesAPIClient], error) { 259 return GetSelector[preferences.PreferencesAPIClient]( 260 "PreferencesSelector", 261 id, 262 preferences.NewPreferencesAPIClient, 263 options..., 264 ), nil 265 } 266 267 // PermissionsSelector returns a Selector[permissions.PermissionsAPIClient]. 268 func PermissionsSelector(id string, options ...Option) (*Selector[permissions.PermissionsAPIClient], error) { 269 return GetSelector[permissions.PermissionsAPIClient]( 270 "PermissionsSelector", 271 id, 272 permissions.NewPermissionsAPIClient, 273 options..., 274 ), nil 275 } 276 277 // AppRegistrySelector returns a Selector[appRegistry.RegistryAPIClient]. 278 func AppRegistrySelector(id string, options ...Option) (*Selector[appRegistry.RegistryAPIClient], error) { 279 return GetSelector[appRegistry.RegistryAPIClient]( 280 "AppRegistrySelector", 281 id, 282 appRegistry.NewRegistryAPIClient, 283 options..., 284 ), nil 285 } 286 287 // AppProviderSelector returns a Selector[appProvider.ProviderAPIClient]. 288 func AppProviderSelector(id string, options ...Option) (*Selector[appProvider.ProviderAPIClient], error) { 289 return GetSelector[appProvider.ProviderAPIClient]( 290 "AppProviderSelector", 291 id, 292 appProvider.NewProviderAPIClient, 293 options..., 294 ), nil 295 } 296 297 // StorageRegistrySelector returns a Selector[storageRegistry.RegistryAPIClient]. 298 func StorageRegistrySelector(id string, options ...Option) (*Selector[storageRegistry.RegistryAPIClient], error) { 299 return GetSelector[storageRegistry.RegistryAPIClient]( 300 "StorageRegistrySelector", 301 id, 302 storageRegistry.NewRegistryAPIClient, 303 options..., 304 ), nil 305 } 306 307 // OCMProviderSelector returns a Selector[storageRegistry.RegistryAPIClient]. 308 func OCMProviderSelector(id string, options ...Option) (*Selector[ocmProvider.ProviderAPIClient], error) { 309 return GetSelector[ocmProvider.ProviderAPIClient]( 310 "OCMProviderSelector", 311 id, 312 ocmProvider.NewProviderAPIClient, 313 options..., 314 ), nil 315 } 316 317 // OCMCoreSelector returns a Selector[ocmCore.OcmCoreAPIClient]. 318 func OCMCoreSelector(id string, options ...Option) (*Selector[ocmCore.OcmCoreAPIClient], error) { 319 return GetSelector[ocmCore.OcmCoreAPIClient]( 320 "OCMCoreSelector", 321 id, 322 ocmCore.NewOcmCoreAPIClient, 323 options..., 324 ), nil 325 } 326 327 // OCMInviteSelector returns a Selector[ocmInvite.InviteAPIClient]. 328 func OCMInviteSelector(id string, options ...Option) (*Selector[ocmInvite.InviteAPIClient], error) { 329 return GetSelector[ocmInvite.InviteAPIClient]( 330 "OCMInviteSelector", 331 id, 332 ocmInvite.NewInviteAPIClient, 333 options..., 334 ), nil 335 } 336 337 // TXSelector returns a Selector[tx.TxAPIClient]. 338 func TXSelector(id string, options ...Option) (*Selector[tx.TxAPIClient], error) { 339 return GetSelector[tx.TxAPIClient]( 340 "TXSelector", 341 id, 342 tx.NewTxAPIClient, 343 options..., 344 ), nil 345 }