github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/config/task_converters_test.go (about) 1 // Copyright 2021 PingCAP, Inc. 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 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 package config 14 15 import ( 16 "fmt" 17 "testing" 18 19 "github.com/pingcap/check" 20 "github.com/pingcap/tidb/pkg/util/filter" 21 "github.com/pingcap/tiflow/dm/config/dbconfig" 22 "github.com/pingcap/tiflow/dm/openapi" 23 "github.com/pingcap/tiflow/dm/openapi/fixtures" 24 "github.com/pingcap/tiflow/dm/pkg/terror" 25 bf "github.com/pingcap/tiflow/pkg/binlog-filter" 26 "github.com/stretchr/testify/require" 27 ) 28 29 func (t *testConfig) TestTaskGetTargetDBCfg(c *check.C) { 30 certAllowedCn := []string{"test"} 31 task := &openapi.Task{ 32 TargetConfig: openapi.TaskTargetDataBase{ 33 Host: "root", 34 Password: "123456", 35 Port: 4000, 36 User: "root", 37 Security: &openapi.Security{CertAllowedCn: &certAllowedCn}, 38 }, 39 } 40 dbCfg := GetTargetDBCfgFromOpenAPITask(task) 41 c.Assert(dbCfg.Host, check.Equals, task.TargetConfig.Host) 42 c.Assert(dbCfg.Password, check.Equals, task.TargetConfig.Password) 43 c.Assert(dbCfg.Port, check.Equals, task.TargetConfig.Port) 44 c.Assert(dbCfg.User, check.Equals, task.TargetConfig.User) 45 c.Assert(dbCfg.Security, check.NotNil) 46 c.Assert([]string{dbCfg.Security.CertAllowedCN[0]}, check.DeepEquals, certAllowedCn) 47 } 48 49 func (t *testConfig) TestOpenAPITaskToSubTaskConfigs(c *check.C) { 50 testNoShardTaskToSubTaskConfigs(c) 51 testShardAndFilterTaskToSubTaskConfigs(c) 52 } 53 54 func testNoShardTaskToSubTaskConfigs(c *check.C) { 55 task, err := fixtures.GenNoShardOpenAPITaskForTest() 56 c.Assert(err, check.IsNil) 57 sourceCfg1, err := SourceCfgFromYamlAndVerify(SampleSourceConfig) 58 c.Assert(err, check.IsNil) 59 source1Name := task.SourceConfig.SourceConf[0].SourceName 60 sourceCfg1.SourceID = task.SourceConfig.SourceConf[0].SourceName 61 sourceCfgMap := map[string]*SourceConfig{source1Name: sourceCfg1} 62 toDBCfg := &dbconfig.DBConfig{ 63 Host: task.TargetConfig.Host, 64 Port: task.TargetConfig.Port, 65 User: task.TargetConfig.User, 66 Password: task.TargetConfig.Password, 67 } 68 // change meta 69 newMeta := "new_dm_meta" 70 task.MetaSchema = &newMeta 71 subTaskConfigList, err := OpenAPITaskToSubTaskConfigs(&task, toDBCfg, sourceCfgMap) 72 c.Assert(err, check.IsNil) 73 c.Assert(subTaskConfigList, check.HasLen, 1) 74 subTaskConfig := subTaskConfigList[0] 75 // check task name and mode 76 c.Assert(subTaskConfig.Name, check.Equals, task.Name) 77 // check task meta 78 c.Assert(subTaskConfig.MetaSchema, check.Equals, *task.MetaSchema) 79 c.Assert(subTaskConfig.Meta, check.IsNil) 80 // check shard config 81 c.Assert(subTaskConfig.ShardMode, check.Equals, "") 82 // check online schema change 83 c.Assert(subTaskConfig.OnlineDDL, check.Equals, true) 84 // check case sensitive 85 c.Assert(subTaskConfig.CaseSensitive, check.Equals, sourceCfg1.CaseSensitive) 86 // check from 87 c.Assert(subTaskConfig.From.Host, check.Equals, sourceCfg1.From.Host) 88 // check to 89 c.Assert(subTaskConfig.To.Host, check.Equals, toDBCfg.Host) 90 // check dumpling loader syncer config 91 c.Assert(subTaskConfig.MydumperConfig.Threads, check.Equals, *task.SourceConfig.FullMigrateConf.ExportThreads) 92 c.Assert(subTaskConfig.LoaderConfig.Dir, check.Equals, fmt.Sprintf( 93 "%s.%s", *task.SourceConfig.FullMigrateConf.DataDir, task.Name)) 94 c.Assert(subTaskConfig.LoaderConfig.PoolSize, check.Equals, *task.SourceConfig.FullMigrateConf.ImportThreads) 95 c.Assert(subTaskConfig.SyncerConfig.WorkerCount, check.Equals, *task.SourceConfig.IncrMigrateConf.ReplThreads) 96 c.Assert(subTaskConfig.SyncerConfig.Batch, check.Equals, *task.SourceConfig.IncrMigrateConf.ReplBatch) 97 // check route 98 c.Assert(subTaskConfig.RouteRules, check.HasLen, 1) 99 rule := subTaskConfig.RouteRules[0] 100 101 sourceSchema := task.TableMigrateRule[0].Source.Schema 102 sourceTable := task.TableMigrateRule[0].Source.Table 103 tartgetSchema := task.TableMigrateRule[0].Target.Schema 104 tartgetTable := task.TableMigrateRule[0].Target.Table 105 106 c.Assert(rule.SchemaPattern, check.Equals, sourceSchema) 107 c.Assert(rule.TablePattern, check.Equals, sourceTable) 108 c.Assert(rule.TargetSchema, check.Equals, *tartgetSchema) 109 c.Assert(rule.TargetTable, check.Equals, *tartgetTable) 110 // check filter 111 c.Assert(subTaskConfig.FilterRules, check.HasLen, 0) 112 // check balist 113 c.Assert(subTaskConfig.BAList, check.NotNil) 114 bAListFromOpenAPITask := &filter.Rules{ 115 DoTables: []*filter.Table{{Schema: sourceSchema, Name: sourceTable}}, 116 } 117 c.Assert(subTaskConfig.BAList, check.DeepEquals, bAListFromOpenAPITask) 118 // check ignore check items 119 c.Assert(subTaskConfig.IgnoreCheckingItems, check.IsNil) 120 } 121 122 func testShardAndFilterTaskToSubTaskConfigs(c *check.C) { 123 task, err := fixtures.GenShardAndFilterOpenAPITaskForTest() 124 c.Assert(err, check.IsNil) 125 sourceCfg1, err := SourceCfgFromYamlAndVerify(SampleSourceConfig) 126 c.Assert(err, check.IsNil) 127 source1Name := task.SourceConfig.SourceConf[0].SourceName 128 sourceCfg1.SourceID = source1Name 129 sourceCfg2, err := SourceCfgFromYamlAndVerify(SampleSourceConfig) 130 c.Assert(err, check.IsNil) 131 source2Name := task.SourceConfig.SourceConf[1].SourceName 132 sourceCfg2.SourceID = source2Name 133 134 toDBCfg := &dbconfig.DBConfig{ 135 Host: task.TargetConfig.Host, 136 Port: task.TargetConfig.Port, 137 User: task.TargetConfig.User, 138 Password: task.TargetConfig.Password, 139 } 140 sourceCfgMap := map[string]*SourceConfig{source1Name: sourceCfg1, source2Name: sourceCfg2} 141 subTaskConfigList, err := OpenAPITaskToSubTaskConfigs(&task, toDBCfg, sourceCfgMap) 142 c.Assert(err, check.IsNil) 143 c.Assert(subTaskConfigList, check.HasLen, 2) 144 145 // check sub task 1 146 subTask1Config := subTaskConfigList[0] 147 // check task name and mode 148 c.Assert(subTask1Config.Name, check.Equals, task.Name) 149 // check task meta 150 c.Assert(subTask1Config.MetaSchema, check.Equals, *task.MetaSchema) 151 c.Assert(subTask1Config.Meta, check.NotNil) 152 c.Assert(subTask1Config.Meta.BinLogGTID, check.Equals, *task.SourceConfig.SourceConf[0].BinlogGtid) 153 c.Assert(subTask1Config.Meta.BinLogName, check.Equals, *task.SourceConfig.SourceConf[0].BinlogName) 154 c.Assert(subTask1Config.Meta.BinLogPos, check.Equals, uint32(*task.SourceConfig.SourceConf[0].BinlogPos)) 155 156 // check shard config 157 c.Assert(subTask1Config.ShardMode, check.Equals, string(openapi.TaskShardModeOptimistic)) 158 c.Assert(subTask1Config.StrictOptimisticShardMode, check.IsTrue) 159 // check online schema change 160 c.Assert(subTask1Config.OnlineDDL, check.Equals, true) 161 // check case sensitive 162 c.Assert(subTask1Config.CaseSensitive, check.Equals, sourceCfg1.CaseSensitive) 163 // check from 164 c.Assert(subTask1Config.From.Host, check.Equals, sourceCfg1.From.Host) 165 // check to 166 c.Assert(subTask1Config.To.Host, check.Equals, toDBCfg.Host) 167 // check dumpling loader syncer config 168 c.Assert(subTask1Config.MydumperConfig.Threads, check.Equals, *task.SourceConfig.FullMigrateConf.ExportThreads) 169 c.Assert(subTask1Config.LoaderConfig.Dir, check.Equals, fmt.Sprintf( 170 "%s.%s", *task.SourceConfig.FullMigrateConf.DataDir, task.Name)) 171 c.Assert(subTask1Config.LoaderConfig.PoolSize, check.Equals, *task.SourceConfig.FullMigrateConf.ImportThreads) 172 c.Assert(subTask1Config.SyncerConfig.WorkerCount, check.Equals, *task.SourceConfig.IncrMigrateConf.ReplThreads) 173 c.Assert(subTask1Config.SyncerConfig.Batch, check.Equals, *task.SourceConfig.IncrMigrateConf.ReplBatch) 174 // check route 175 c.Assert(subTask1Config.RouteRules, check.HasLen, 1) 176 rule := subTask1Config.RouteRules[0] 177 source1Schema := task.TableMigrateRule[0].Source.Schema 178 source1Table := task.TableMigrateRule[0].Source.Table 179 tartgetSchema := task.TableMigrateRule[0].Target.Schema 180 tartgetTable := task.TableMigrateRule[0].Target.Table 181 c.Assert(rule.SchemaPattern, check.Equals, source1Schema) 182 c.Assert(rule.TablePattern, check.Equals, source1Table) 183 c.Assert(rule.TargetSchema, check.Equals, *tartgetSchema) 184 c.Assert(rule.TargetTable, check.Equals, *tartgetTable) 185 // check filter 186 filterARule, ok := task.BinlogFilterRule.Get("filterA") 187 c.Assert(ok, check.IsTrue) 188 filterIgnoreEvents := *filterARule.IgnoreEvent 189 c.Assert(filterIgnoreEvents, check.HasLen, 1) 190 filterEvents := []bf.EventType{bf.EventType(filterIgnoreEvents[0])} 191 filterRulesFromOpenAPITask := &bf.BinlogEventRule{ 192 Action: bf.Ignore, 193 Events: filterEvents, 194 SQLPattern: *filterARule.IgnoreSql, 195 SchemaPattern: source1Schema, 196 TablePattern: source1Table, 197 } 198 c.Assert(filterRulesFromOpenAPITask.Valid(), check.IsNil) 199 c.Assert(subTask1Config.FilterRules, check.HasLen, 1) 200 c.Assert(subTask1Config.FilterRules[0], check.DeepEquals, filterRulesFromOpenAPITask) 201 202 // check balist 203 c.Assert(subTask1Config.BAList, check.NotNil) 204 bAListFromOpenAPITask := &filter.Rules{ 205 DoTables: []*filter.Table{{Schema: source1Schema, Name: source1Table}}, 206 } 207 c.Assert(subTask1Config.BAList, check.DeepEquals, bAListFromOpenAPITask) 208 // check ignore check items 209 c.Assert(subTask1Config.IgnoreCheckingItems, check.IsNil) 210 211 // check sub task 2 212 subTask2Config := subTaskConfigList[1] 213 // check task name and mode 214 c.Assert(subTask2Config.Name, check.Equals, task.Name) 215 // check task meta 216 c.Assert(subTask2Config.MetaSchema, check.Equals, *task.MetaSchema) 217 c.Assert(subTask2Config.Meta, check.NotNil) 218 c.Assert(subTask2Config.Meta.BinLogGTID, check.Equals, *task.SourceConfig.SourceConf[1].BinlogGtid) 219 c.Assert(subTask2Config.Meta.BinLogName, check.Equals, *task.SourceConfig.SourceConf[1].BinlogName) 220 c.Assert(subTask2Config.Meta.BinLogPos, check.Equals, uint32(*task.SourceConfig.SourceConf[1].BinlogPos)) 221 // check shard config 222 c.Assert(subTask2Config.ShardMode, check.Equals, string(openapi.TaskShardModeOptimistic)) 223 // check online schema change 224 c.Assert(subTask2Config.OnlineDDL, check.Equals, true) 225 // check case sensitive 226 c.Assert(subTask2Config.CaseSensitive, check.Equals, sourceCfg2.CaseSensitive) 227 // check from 228 c.Assert(subTask2Config.From.Host, check.Equals, sourceCfg2.From.Host) 229 // check to 230 c.Assert(subTask2Config.To.Host, check.Equals, toDBCfg.Host) 231 // check dumpling loader syncer config 232 c.Assert(subTask2Config.MydumperConfig.Threads, check.Equals, *task.SourceConfig.FullMigrateConf.ExportThreads) 233 c.Assert(subTask2Config.LoaderConfig.Dir, check.Equals, fmt.Sprintf( 234 "%s.%s", *task.SourceConfig.FullMigrateConf.DataDir, task.Name)) 235 c.Assert(subTask2Config.LoaderConfig.PoolSize, check.Equals, *task.SourceConfig.FullMigrateConf.ImportThreads) 236 c.Assert(subTask2Config.SyncerConfig.WorkerCount, check.Equals, *task.SourceConfig.IncrMigrateConf.ReplThreads) 237 c.Assert(subTask2Config.SyncerConfig.Batch, check.Equals, *task.SourceConfig.IncrMigrateConf.ReplBatch) 238 // check route 239 c.Assert(subTask2Config.RouteRules, check.HasLen, 1) 240 rule = subTask2Config.RouteRules[0] 241 source2Schema := task.TableMigrateRule[1].Source.Schema 242 source2Table := task.TableMigrateRule[1].Source.Table 243 c.Assert(rule.SchemaPattern, check.Equals, source2Schema) 244 c.Assert(rule.TablePattern, check.Equals, source2Table) 245 c.Assert(rule.TargetSchema, check.Equals, *tartgetSchema) 246 c.Assert(rule.TargetTable, check.Equals, *tartgetTable) 247 // check filter 248 _, ok = task.BinlogFilterRule.Get("filterB") 249 c.Assert(ok, check.IsFalse) 250 c.Assert(subTask2Config.FilterRules, check.HasLen, 0) 251 // check balist 252 c.Assert(subTask2Config.BAList, check.NotNil) 253 bAListFromOpenAPITask = &filter.Rules{ 254 DoTables: []*filter.Table{{Schema: source2Schema, Name: source2Table}}, 255 } 256 c.Assert(subTask2Config.BAList, check.DeepEquals, bAListFromOpenAPITask) 257 // check ignore check items 258 c.Assert(subTask2Config.IgnoreCheckingItems, check.IsNil) 259 } 260 261 func (t *testConfig) TestSubTaskConfigsToOpenAPITask(c *check.C) { 262 testNoShardSubTaskConfigsToOpenAPITask(c) 263 testShardAndFilterSubTaskConfigsToOpenAPITask(c) 264 } 265 266 func testNoShardSubTaskConfigsToOpenAPITask(c *check.C) { 267 task, err := fixtures.GenNoShardOpenAPITaskForTest() 268 c.Assert(err, check.IsNil) 269 sourceCfg1, err := SourceCfgFromYamlAndVerify(SampleSourceConfig) 270 c.Assert(err, check.IsNil) 271 source1Name := task.SourceConfig.SourceConf[0].SourceName 272 sourceCfg1.SourceID = task.SourceConfig.SourceConf[0].SourceName 273 sourceCfgMap := map[string]*SourceConfig{source1Name: sourceCfg1} 274 toDBCfg := &dbconfig.DBConfig{ 275 Host: task.TargetConfig.Host, 276 Port: task.TargetConfig.Port, 277 User: task.TargetConfig.User, 278 Password: task.TargetConfig.Password, 279 } 280 subTaskConfigList, err := OpenAPITaskToSubTaskConfigs(&task, toDBCfg, sourceCfgMap) 281 c.Assert(err, check.IsNil) 282 c.Assert(subTaskConfigList, check.HasLen, 1) 283 284 // prepare sub task config 285 subTaskConfigMap := make(map[string]map[string]*SubTaskConfig) 286 subTaskConfigMap[task.Name] = make(map[string]*SubTaskConfig) 287 subTaskConfigMap[task.Name][source1Name] = subTaskConfigList[0] 288 289 taskList := SubTaskConfigsToOpenAPITaskList(subTaskConfigMap) 290 c.Assert(taskList, check.HasLen, 1) 291 newTask := taskList[0] 292 c.Assert(&task, check.DeepEquals, newTask) 293 } 294 295 func testShardAndFilterSubTaskConfigsToOpenAPITask(c *check.C) { 296 task, err := fixtures.GenShardAndFilterOpenAPITaskForTest() 297 c.Assert(err, check.IsNil) 298 sourceCfg1, err := SourceCfgFromYamlAndVerify(SampleSourceConfig) 299 c.Assert(err, check.IsNil) 300 source1Name := task.SourceConfig.SourceConf[0].SourceName 301 sourceCfg1.SourceID = source1Name 302 sourceCfg2, err := SourceCfgFromYamlAndVerify(SampleSourceConfig) 303 c.Assert(err, check.IsNil) 304 source2Name := task.SourceConfig.SourceConf[1].SourceName 305 sourceCfg2.SourceID = source2Name 306 307 toDBCfg := &dbconfig.DBConfig{ 308 Host: task.TargetConfig.Host, 309 Port: task.TargetConfig.Port, 310 User: task.TargetConfig.User, 311 Password: task.TargetConfig.Password, 312 } 313 sourceCfgMap := map[string]*SourceConfig{source1Name: sourceCfg1, source2Name: sourceCfg2} 314 subTaskConfigList, err := OpenAPITaskToSubTaskConfigs(&task, toDBCfg, sourceCfgMap) 315 c.Assert(err, check.IsNil) 316 c.Assert(subTaskConfigList, check.HasLen, 2) 317 318 // prepare sub task config 319 subTaskConfigMap := make(map[string]map[string]*SubTaskConfig) 320 subTaskConfigMap[task.Name] = make(map[string]*SubTaskConfig) 321 subTaskConfigMap[task.Name][source1Name] = subTaskConfigList[0] 322 subTaskConfigMap[task.Name][source2Name] = subTaskConfigList[1] 323 324 taskList := SubTaskConfigsToOpenAPITaskList(subTaskConfigMap) 325 c.Assert(taskList, check.HasLen, 1) 326 newTask := taskList[0] 327 328 // because subtask config not have filter-rule-name, so we need to add it manually 329 oldRuleName := "filterA" 330 newRuleName := genFilterRuleName(source1Name, 0) 331 oldRule, ok := task.BinlogFilterRule.Get(oldRuleName) 332 c.Assert(ok, check.IsTrue) 333 newRule := openapi.Task_BinlogFilterRule{} 334 newRule.Set(newRuleName, oldRule) 335 task.BinlogFilterRule = &newRule 336 task.TableMigrateRule[0].BinlogFilterRule = &[]string{newRuleName} 337 338 // because map key is not sorted, so generated array (source_conf and table_migrate_rule) order may not same with old one. 339 // so we need to fix it manually. 340 if task.SourceConfig.SourceConf[0].SourceName != newTask.SourceConfig.SourceConf[0].SourceName { 341 task.SourceConfig.SourceConf[0], task.SourceConfig.SourceConf[1] = task.SourceConfig.SourceConf[1], task.SourceConfig.SourceConf[0] 342 } 343 if task.TableMigrateRule[0].Source.SourceName != newTask.TableMigrateRule[0].Source.SourceName { 344 task.TableMigrateRule[0], task.TableMigrateRule[1] = task.TableMigrateRule[1], task.TableMigrateRule[0] 345 } 346 347 c.Assert(&task, check.DeepEquals, newTask) 348 } 349 350 func TestConvertWithIgnoreCheckItems(t *testing.T) { 351 task, err := fixtures.GenNoShardOpenAPITaskForTest() 352 require.NoError(t, err) 353 ignoreCheckingItems := []string{DumpPrivilegeChecking, VersionChecking} 354 task.IgnoreCheckingItems = &ignoreCheckingItems 355 sourceCfg1, err := SourceCfgFromYamlAndVerify(SampleSourceConfig) 356 require.NoError(t, err) 357 source1Name := task.SourceConfig.SourceConf[0].SourceName 358 sourceCfg1.SourceID = task.SourceConfig.SourceConf[0].SourceName 359 sourceCfgMap := map[string]*SourceConfig{source1Name: sourceCfg1} 360 toDBCfg := &dbconfig.DBConfig{ 361 Host: task.TargetConfig.Host, 362 Port: task.TargetConfig.Port, 363 User: task.TargetConfig.User, 364 Password: task.TargetConfig.Password, 365 } 366 subTaskConfigList, err := OpenAPITaskToSubTaskConfigs(&task, toDBCfg, sourceCfgMap) 367 require.NoError(t, err) 368 require.Equal(t, 1, len(subTaskConfigList)) 369 370 // prepare sub task config 371 subTaskConfigMap := make(map[string]map[string]*SubTaskConfig) 372 subTaskConfigMap[task.Name] = make(map[string]*SubTaskConfig) 373 subTaskConfigMap[task.Name][source1Name] = subTaskConfigList[0] 374 375 taskList := SubTaskConfigsToOpenAPITaskList(subTaskConfigMap) 376 require.Equal(t, 1, len(taskList)) 377 newTask := taskList[0] 378 require.Equal(t, *newTask.IgnoreCheckingItems, ignoreCheckingItems) 379 require.Equal(t, *newTask, task) 380 } 381 382 func TestConvertBetweenOpenAPITaskAndTaskConfig(t *testing.T) { 383 // one source task 384 task, err := fixtures.GenNoShardOpenAPITaskForTest() 385 require.NoError(t, err) 386 387 sourceCfg1, err := SourceCfgFromYamlAndVerify(SampleSourceConfig) 388 require.NoError(t, err) 389 source1Name := task.SourceConfig.SourceConf[0].SourceName 390 sourceCfg1.SourceID = source1Name 391 sourceCfgMap := map[string]*SourceConfig{source1Name: sourceCfg1} 392 393 taskCfg, err := OpenAPITaskToTaskConfig(&task, sourceCfgMap) 394 require.NoError(t, err) 395 require.NotNil(t, taskCfg) 396 task1, err := TaskConfigToOpenAPITask(taskCfg, sourceCfgMap) 397 require.NoError(t, err) 398 require.NotNil(t, task1) 399 require.EqualValues(t, task1, &task) 400 401 // test update some fields in task 402 { 403 batch := 1000 404 task.SourceConfig.IncrMigrateConf.ReplBatch = &batch 405 taskCfg2, err2 := OpenAPITaskToTaskConfig(&task, sourceCfgMap) 406 require.NoError(t, err2) 407 require.Equal(t, batch, taskCfg2.MySQLInstances[0].Syncer.Batch) 408 for _, cfg := range taskCfg2.Syncers { 409 require.Equal(t, batch, cfg.Batch) 410 } 411 412 // test update some fields in taskConfig 413 batch = 1 414 for _, cfg := range taskCfg2.Syncers { 415 cfg.Batch = batch 416 } 417 task2, err3 := TaskConfigToOpenAPITask(taskCfg2, sourceCfgMap) 418 require.NoError(t, err3) 419 require.Equal(t, batch, *task2.SourceConfig.IncrMigrateConf.ReplBatch) 420 } 421 422 // test update route 423 { 424 require.Len(t, task.TableMigrateRule, 1) 425 sourceSchema := task.TableMigrateRule[0].Source.Schema 426 targetSchema := *task.TableMigrateRule[0].Target.Schema 427 // only route schema 428 task.TableMigrateRule[0].Source = struct { 429 Schema string `json:"schema"` 430 SourceName string `json:"source_name"` 431 Table string `json:"table"` 432 }{ 433 SourceName: source1Name, 434 Schema: sourceSchema, 435 } 436 task.TableMigrateRule[0].Target = &struct { 437 Schema *string `json:"schema,omitempty"` 438 Table *string `json:"table,omitempty"` 439 }{ 440 Schema: &targetSchema, 441 } 442 taskCfg, err = OpenAPITaskToTaskConfig(&task, sourceCfgMap) 443 require.NoError(t, err) 444 require.Len(t, taskCfg.Routes, 1) 445 var routeKey string 446 for k := range taskCfg.Routes { 447 routeKey = k 448 } 449 450 // validate route rule in taskCfg 451 require.Equal(t, sourceSchema, taskCfg.Routes[routeKey].SchemaPattern) 452 require.Equal(t, "", taskCfg.Routes[routeKey].TablePattern) 453 require.Equal(t, targetSchema, taskCfg.Routes[routeKey].TargetSchema) 454 require.Equal(t, "", taskCfg.Routes[routeKey].TargetTable) 455 456 // validate baList in taskCfg, just do DBs because there is no table route rule 457 require.Len(t, taskCfg.BAList, 1) 458 require.Len(t, taskCfg.MySQLInstances, 1) 459 baListName := taskCfg.MySQLInstances[0].BAListName 460 require.Len(t, taskCfg.BAList[baListName].DoTables, 0) 461 require.Len(t, taskCfg.BAList[baListName].DoDBs, 1) 462 require.Equal(t, sourceSchema, taskCfg.BAList[baListName].DoDBs[0]) 463 464 // convert back to openapi.Task 465 taskAfterConvert, err2 := TaskConfigToOpenAPITask(taskCfg, sourceCfgMap) 466 require.NoError(t, err2) 467 require.NotNil(t, taskAfterConvert) 468 require.EqualValues(t, taskAfterConvert, &task) 469 470 // only route table will meet error 471 sourceTable := "tb" 472 targetTable := "tb1" 473 task.TableMigrateRule[0].Source = struct { 474 Schema string `json:"schema"` 475 SourceName string `json:"source_name"` 476 Table string `json:"table"` 477 }{ 478 SourceName: source1Name, 479 Schema: sourceSchema, 480 Table: sourceTable, 481 } 482 task.TableMigrateRule[0].Target = &struct { 483 Schema *string `json:"schema,omitempty"` 484 Table *string `json:"table,omitempty"` 485 }{ 486 Table: &targetTable, 487 } 488 _, err = OpenAPITaskToTaskConfig(&task, sourceCfgMap) 489 require.True(t, terror.ErrConfigGenTableRouter.Equal(err)) 490 491 // route both 492 task.TableMigrateRule[0].Source = struct { 493 Schema string `json:"schema"` 494 SourceName string `json:"source_name"` 495 Table string `json:"table"` 496 }{ 497 SourceName: source1Name, 498 Schema: sourceSchema, 499 Table: sourceTable, 500 } 501 task.TableMigrateRule[0].Target = &struct { 502 Schema *string `json:"schema,omitempty"` 503 Table *string `json:"table,omitempty"` 504 }{ 505 Schema: &targetSchema, 506 Table: &targetTable, 507 } 508 taskCfg, err = OpenAPITaskToTaskConfig(&task, sourceCfgMap) 509 require.NoError(t, err) 510 511 // validate route rule in taskCfg 512 require.Equal(t, sourceSchema, taskCfg.Routes[routeKey].SchemaPattern) 513 require.Equal(t, sourceTable, taskCfg.Routes[routeKey].TablePattern) 514 require.Equal(t, targetSchema, taskCfg.Routes[routeKey].TargetSchema) 515 require.Equal(t, targetTable, taskCfg.Routes[routeKey].TargetTable) 516 517 // validate baList in taskCfg, just do Tables because there is a table route rule 518 require.Len(t, taskCfg.BAList[baListName].DoDBs, 0) 519 require.Len(t, taskCfg.BAList[baListName].DoTables, 1) 520 require.Equal(t, sourceSchema, taskCfg.BAList[baListName].DoTables[0].Schema) 521 require.Equal(t, sourceTable, taskCfg.BAList[baListName].DoTables[0].Name) 522 523 // convert back to openapi.Task 524 taskAfterConvert, err = TaskConfigToOpenAPITask(taskCfg, sourceCfgMap) 525 require.NoError(t, err) 526 require.NotNil(t, taskAfterConvert) 527 require.EqualValues(t, taskAfterConvert, &task) 528 529 // no route and only sync one table 530 task.TableMigrateRule[0].Target = nil 531 taskCfg, err = OpenAPITaskToTaskConfig(&task, sourceCfgMap) 532 require.NoError(t, err) 533 require.Len(t, taskCfg.Routes, 0) 534 535 // validate baList in taskCfg, just do Tables because there is a table route rule 536 require.Len(t, taskCfg.BAList[baListName].DoDBs, 0) 537 require.Len(t, taskCfg.BAList[baListName].DoTables, 1) 538 require.Equal(t, sourceSchema, taskCfg.BAList[baListName].DoTables[0].Schema) 539 require.Equal(t, sourceTable, taskCfg.BAList[baListName].DoTables[0].Name) 540 541 taskAfterConvert, err = TaskConfigToOpenAPITask(taskCfg, sourceCfgMap) 542 require.NoError(t, err) 543 require.NotNil(t, taskAfterConvert) 544 require.EqualValues(t, taskAfterConvert, &task) 545 546 // no route and sync one schema 547 task.TableMigrateRule[0].Source = struct { 548 Schema string `json:"schema"` 549 SourceName string `json:"source_name"` 550 Table string `json:"table"` 551 }{ 552 SourceName: source1Name, 553 Schema: sourceSchema, 554 Table: "", 555 } 556 taskCfg, err = OpenAPITaskToTaskConfig(&task, sourceCfgMap) 557 require.NoError(t, err) 558 require.Len(t, taskCfg.Routes, 0) 559 560 // validate baList in taskCfg, just do DBs because there is no table route rule 561 require.Len(t, taskCfg.BAList[baListName].DoTables, 0) 562 require.Len(t, taskCfg.BAList[baListName].DoDBs, 1) 563 require.Equal(t, sourceSchema, taskCfg.BAList[baListName].DoDBs[0]) 564 565 taskAfterConvert, err = TaskConfigToOpenAPITask(taskCfg, sourceCfgMap) 566 require.NoError(t, err) 567 require.NotNil(t, taskAfterConvert) 568 require.EqualValues(t, taskAfterConvert, &task) 569 } 570 571 // test update filter 572 { 573 // no filter no change 574 require.Nil(t, task.BinlogFilterRule) 575 taskCfg, err = OpenAPITaskToTaskConfig(&task, sourceCfgMap) 576 require.NoError(t, err) 577 taskAfterConvert, err := TaskConfigToOpenAPITask(taskCfg, sourceCfgMap) 578 require.NoError(t, err) 579 require.NotNil(t, taskAfterConvert) 580 require.EqualValues(t, taskAfterConvert, &task) 581 582 // filter both 583 sourceSchema := task.TableMigrateRule[0].Source.Schema 584 sourceTable := task.TableMigrateRule[0].Source.Table 585 ignoreEvent := []string{"drop database"} 586 ignoreSQL := []string{"^Drop"} 587 ruleName := genFilterRuleName(source1Name, 0) 588 ruleNameList := []string{ruleName} 589 rule := openapi.TaskBinLogFilterRule{IgnoreEvent: &ignoreEvent, IgnoreSql: &ignoreSQL} 590 ruleM := &openapi.Task_BinlogFilterRule{} 591 ruleM.Set(ruleName, rule) 592 task.BinlogFilterRule = ruleM 593 task.TableMigrateRule[0].BinlogFilterRule = &ruleNameList 594 595 taskCfg, err = OpenAPITaskToTaskConfig(&task, sourceCfgMap) 596 require.NoError(t, err) 597 require.Len(t, taskCfg.Filters, 1) 598 require.Len(t, taskCfg.MySQLInstances[0].FilterRules, 1) 599 filterName := taskCfg.MySQLInstances[0].FilterRules[0] 600 require.Equal(t, bf.Ignore, taskCfg.Filters[filterName].Action) 601 require.Equal(t, sourceSchema, taskCfg.Filters[filterName].SchemaPattern) 602 require.Equal(t, sourceTable, taskCfg.Filters[filterName].TablePattern) 603 require.Len(t, taskCfg.Filters[filterName].SQLPattern, 1) 604 require.Equal(t, ignoreSQL[0], taskCfg.Filters[filterName].SQLPattern[0]) 605 require.Len(t, taskCfg.Filters[filterName].Events, 1) 606 require.Equal(t, ignoreEvent[0], string(taskCfg.Filters[filterName].Events[0])) 607 608 // convert back to openapi.Task 609 taskAfterConvert, err = TaskConfigToOpenAPITask(taskCfg, sourceCfgMap) 610 require.NoError(t, err) 611 require.NotNil(t, taskAfterConvert) 612 require.EqualValues(t, taskAfterConvert, &task) 613 614 // only filter events 615 rule = openapi.TaskBinLogFilterRule{IgnoreEvent: &ignoreEvent} 616 ruleM.Set(ruleName, rule) 617 taskCfg, err = OpenAPITaskToTaskConfig(&task, sourceCfgMap) 618 require.NoError(t, err) 619 require.Len(t, taskCfg.Filters[filterName].SQLPattern, 0) 620 621 taskAfterConvert, err = TaskConfigToOpenAPITask(taskCfg, sourceCfgMap) 622 ruleMAfterConvert := taskAfterConvert.BinlogFilterRule 623 ruleAfterConvert, ok := ruleMAfterConvert.Get(ruleName) 624 require.True(t, ok) 625 require.Nil(t, ruleAfterConvert.IgnoreSql) 626 require.NoError(t, err) 627 require.NotNil(t, taskAfterConvert) 628 require.EqualValues(t, taskAfterConvert, &task) 629 } 630 }