vitess.io/vitess@v0.16.2/go/vt/srvtopo/read_only_server.go (about) 1 /* 2 Copyright 2021 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package srvtopo 18 19 import ( 20 "context" 21 "fmt" 22 23 topodatapb "vitess.io/vitess/go/vt/proto/topodata" 24 vschemapb "vitess.io/vitess/go/vt/proto/vschema" 25 "vitess.io/vitess/go/vt/topo" 26 ) 27 28 // NewReadOnlyServer wraps the topo server passed by the provided implementation 29 // and prevents any changes from being made to it. 30 func NewReadOnlyServer(underlying Server) (Server, error) { 31 ros := readOnlyServer{underlying: underlying} 32 33 if underlying == nil { 34 return ros, ErrNilUnderlyingServer 35 } 36 37 topoServer, err := underlying.GetTopoServer() 38 if err != nil || topoServer == nil { 39 return ros, topo.NewError(topo.NoImplementation, fmt.Sprintf("could not get underlying topo server: %v", err)) 40 } 41 42 err = topoServer.SetReadOnly(true) 43 if err != nil { 44 return ros, topo.NewError(topo.NoReadOnlyImplementation, fmt.Sprintf("could not provide read-only topo server: %v", err)) 45 } 46 47 return ros, nil 48 } 49 50 // ReadOnlyServer wraps an underlying Server to ensure the topo server access is read-only 51 type readOnlyServer struct { 52 underlying Server 53 } 54 55 // GetTopoServer returns a read-only topo server 56 func (ros readOnlyServer) GetTopoServer() (*topo.Server, error) { 57 topoServer, err := ros.underlying.GetTopoServer() 58 if err != nil || topoServer == nil { 59 return nil, topo.NewError(topo.NoImplementation, fmt.Sprintf("could not get underlying topo server: %v", err)) 60 } 61 62 // The topo server should already be read-only, from the constructor, but as an extra 63 // safety precaution and guardrail let's ensure that it is before handing it out 64 err = topoServer.SetReadOnly(true) 65 if err != nil { 66 return nil, topo.NewError(topo.NoReadOnlyImplementation, fmt.Sprintf("could not provide read-only topo server: %v", err)) 67 } 68 readOnly, err := topoServer.IsReadOnly() 69 if err != nil || !readOnly { 70 return nil, topo.NewError(topo.NoReadOnlyImplementation, fmt.Sprintf("could not provide read-only topo server: %v", err)) 71 } 72 73 return topoServer, err 74 } 75 76 // GetSrvKeyspaceNames returns the list of keyspaces served in the provided cell from the underlying server 77 func (ros readOnlyServer) GetSrvKeyspaceNames(ctx context.Context, cell string, staleOK bool) ([]string, error) { 78 return ros.underlying.GetSrvKeyspaceNames(ctx, cell, staleOK) 79 } 80 81 // GetSrvKeyspace returns the SrvKeyspace for a cell/keyspace from the underlying server 82 func (ros readOnlyServer) GetSrvKeyspace(ctx context.Context, cell, keyspace string) (*topodatapb.SrvKeyspace, error) { 83 return ros.underlying.GetSrvKeyspace(ctx, cell, keyspace) 84 } 85 86 func (ros readOnlyServer) WatchSrvKeyspace(ctx context.Context, cell, keyspace string, callback func(*topodatapb.SrvKeyspace, error) bool) { 87 ros.underlying.WatchSrvKeyspace(ctx, cell, keyspace, callback) 88 } 89 90 // WatchSrvVSchema starts watching the SrvVSchema object for the provided cell. It will call the callback when 91 // a new value or an error occurs. 92 func (ros readOnlyServer) WatchSrvVSchema(ctx context.Context, cell string, callback func(*vschemapb.SrvVSchema, error) bool) { 93 ros.underlying.WatchSrvVSchema(ctx, cell, callback) 94 }