vitess.io/vitess@v0.16.2/go/vt/topo/helpers/compare.go (about) 1 /* 2 Copyright 2019 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 helpers contains a few utility classes to handle topo.Server 18 // objects, and transitions from one topo implementation to another. 19 package helpers 20 21 import ( 22 "reflect" 23 24 "google.golang.org/protobuf/proto" 25 26 "context" 27 28 "vitess.io/vitess/go/vt/proto/vtrpc" 29 "vitess.io/vitess/go/vt/topo" 30 "vitess.io/vitess/go/vt/vterrors" 31 ) 32 33 // CompareKeyspaces will compare the keyspaces in the destination topo. 34 func CompareKeyspaces(ctx context.Context, fromTS, toTS *topo.Server) error { 35 keyspaces, err := fromTS.GetKeyspaces(ctx) 36 if err != nil { 37 return vterrors.Wrapf(err, "GetKeyspace(%v)", keyspaces) 38 } 39 40 for _, keyspace := range keyspaces { 41 42 fromKs, err := fromTS.GetKeyspace(ctx, keyspace) 43 if err != nil { 44 return vterrors.Wrapf(err, "GetKeyspace(%v)", keyspace) 45 } 46 47 toKs, err := toTS.GetKeyspace(ctx, keyspace) 48 if err != nil { 49 return vterrors.Wrapf(err, "GetKeyspace(%v)", keyspace) 50 } 51 52 if !reflect.DeepEqual(fromKs.Keyspace, toKs.Keyspace) { 53 return vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, "Keyspace: %v does not match between from and to topology", keyspace) 54 } 55 56 fromVs, err := fromTS.GetVSchema(ctx, keyspace) 57 switch { 58 case err == nil: 59 // Nothing to do. 60 case topo.IsErrType(err, topo.NoNode): 61 // Nothing to do. 62 default: 63 return vterrors.Wrapf(err, "GetVSchema(%v)", keyspace) 64 } 65 66 toVs, err := toTS.GetVSchema(ctx, keyspace) 67 switch { 68 case err == nil: 69 // Nothing to do. 70 case topo.IsErrType(err, topo.NoNode): 71 // Nothing to do. 72 default: 73 return vterrors.Wrapf(err, "GetVSchema(%v)", keyspace) 74 } 75 76 if !reflect.DeepEqual(fromVs, toVs) { 77 return vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, "Vschema for keyspace: %v does not match between from and to topology", keyspace) 78 } 79 } 80 return nil 81 } 82 83 // CompareShards will compare the shards in the destination topo. 84 func CompareShards(ctx context.Context, fromTS, toTS *topo.Server) error { 85 keyspaces, err := fromTS.GetKeyspaces(ctx) 86 if err != nil { 87 return vterrors.Wrapf(err, "fromTS.GetKeyspaces") 88 } 89 90 for _, keyspace := range keyspaces { 91 shards, err := fromTS.GetShardNames(ctx, keyspace) 92 if err != nil { 93 return vterrors.Wrapf(err, "GetShardNames(%v)", keyspace) 94 } 95 96 for _, shard := range shards { 97 fromSi, err := fromTS.GetShard(ctx, keyspace, shard) 98 if err != nil { 99 return vterrors.Wrapf(err, "GetShard(%v, %v)", keyspace, shard) 100 } 101 toSi, err := toTS.GetShard(ctx, keyspace, shard) 102 if err != nil { 103 return vterrors.Wrapf(err, "GetShard(%v, %v)", keyspace, shard) 104 } 105 106 if !reflect.DeepEqual(fromSi.Shard, toSi.Shard) { 107 return vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, "Shard %v for keyspace: %v does not match between from and to topology", shard, keyspace) 108 } 109 } 110 } 111 return nil 112 } 113 114 // CompareTablets will compare the tablets in the destination topo. 115 func CompareTablets(ctx context.Context, fromTS, toTS *topo.Server) error { 116 cells, err := fromTS.GetKnownCells(ctx) 117 if err != nil { 118 return vterrors.Wrapf(err, "fromTS.GetKnownCells") 119 } 120 121 for _, cell := range cells { 122 tabletAliases, err := fromTS.GetTabletAliasesByCell(ctx, cell) 123 if err != nil { 124 return vterrors.Wrapf(err, "GetTabletsByCell(%v)", cell) 125 } 126 for _, tabletAlias := range tabletAliases { 127 128 // read the source tablet 129 fromTi, err := fromTS.GetTablet(ctx, tabletAlias) 130 if err != nil { 131 return vterrors.Wrapf(err, "GetTablet(%v)", tabletAlias) 132 } 133 toTi, err := toTS.GetTablet(ctx, tabletAlias) 134 if err != nil { 135 return vterrors.Wrapf(err, "GetTablet(%v)", tabletAlias) 136 } 137 if !reflect.DeepEqual(fromTi.Tablet, toTi.Tablet) { 138 return vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, "Tablet %v: does not match between from and to topology", tabletAlias) 139 } 140 } 141 } 142 return nil 143 } 144 145 // CompareShardReplications will compare the ShardReplication objects in 146 // the destination topo. 147 func CompareShardReplications(ctx context.Context, fromTS, toTS *topo.Server) error { 148 keyspaces, err := fromTS.GetKeyspaces(ctx) 149 if err != nil { 150 return vterrors.Wrapf(err, "fromTS.GetKeyspaces") 151 } 152 cells, err := fromTS.GetCellInfoNames(ctx) 153 if err != nil { 154 return vterrors.Wrap(err, "GetCellInfoNames()") 155 } 156 157 for _, keyspace := range keyspaces { 158 shards, err := fromTS.GetShardNames(ctx, keyspace) 159 if err != nil { 160 return vterrors.Wrapf(err, "GetShardNames(%v)", keyspace) 161 } 162 163 for _, shard := range shards { 164 for _, cell := range cells { 165 fromSRi, err := fromTS.GetShardReplication(ctx, cell, keyspace, shard) 166 if err != nil { 167 return vterrors.Wrapf(err, "GetShardReplication(%v, %v, %v)", cell, keyspace, shard) 168 } 169 toSRi, err := toTS.GetShardReplication(ctx, cell, keyspace, shard) 170 if err != nil { 171 return vterrors.Wrapf(err, "GetShardReplication(%v, %v, %v)", cell, keyspace, shard) 172 } 173 if !reflect.DeepEqual(fromSRi.ShardReplication, toSRi.ShardReplication) { 174 return vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, 175 "Shard Replication in cell %v, keyspace %v, shard %v: does not match between from and to topology", 176 cell, 177 keyspace, 178 shard) 179 } 180 } 181 } 182 } 183 return nil 184 } 185 186 // CompareRoutingRules will compare the routing rules in the destination topo. 187 func CompareRoutingRules(ctx context.Context, fromTS, toTS *topo.Server) error { 188 rrFrom, err := fromTS.GetRoutingRules(ctx) 189 if err != nil { 190 return vterrors.Wrapf(err, "GetKeyspace(from)") 191 } 192 rrTo, err := toTS.GetRoutingRules(ctx) 193 if err != nil { 194 return vterrors.Wrapf(err, "GetKeyspace(to)") 195 } 196 if !proto.Equal(rrFrom, rrTo) { 197 return vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, "routing rules: %v does not match %v", rrFrom, rrTo) 198 } 199 return nil 200 }