github.com/pingcap/ticdc@v0.0.0-20220526033649-485a10ef2652/integration/framework/docker_env.go (about) 1 // Copyright 2020 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 14 package framework 15 16 import ( 17 "context" 18 "database/sql" 19 "fmt" 20 "os/exec" 21 22 "github.com/pingcap/log" 23 cerrors "github.com/pingcap/ticdc/pkg/errors" 24 "github.com/pingcap/ticdc/pkg/retry" 25 "go.uber.org/zap" 26 ) 27 28 const ( 29 // UpstreamDSN is upstream database dsn 30 UpstreamDSN = "root@tcp(127.0.0.1:4000)/" 31 // DownstreamDSN is downstream database dsn 32 DownstreamDSN = "root@tcp(127.0.0.1:5000)/" 33 ) 34 35 // DockerEnv represents the docker-compose service 36 type DockerEnv struct { 37 DockerComposeOperator 38 } 39 40 // Reset implements Environment 41 func (e *DockerEnv) Reset() { 42 stdout, err := e.ExecInController(`/cdc cli unsafe reset --no-confirm --pd="http://upstream-pd:2379"`) 43 if err != nil { 44 log.Fatal("ResetEnv: cannot reset the cdc cluster", zap.ByteString("stdout", stdout), zap.Error(err)) 45 } 46 log.Info("ResetEnv: reset the cdc cluster", zap.ByteString("stdout", stdout)) 47 48 upstream, err := sql.Open("mysql", UpstreamDSN) 49 if err != nil { 50 log.Fatal("ResetEnv: cannot connect to upstream database", zap.Error(err)) 51 } 52 defer upstream.Close() 53 if err := dropAllSchemas(upstream); err != nil { 54 log.Fatal("ResetEnv: error found when dropping all schema", zap.Error(err)) 55 } 56 57 downstream, err := sql.Open("mysql", DownstreamDSN) 58 if err != nil { 59 log.Fatal("ResetEnv: cannot connect to downstream database", zap.Error(err)) 60 } 61 defer downstream.Close() 62 if err := dropAllSchemas(downstream); err != nil { 63 log.Fatal("ResetEnv: error found when dropping all schema", zap.Error(err)) 64 } 65 } 66 67 // RunTest implements Environment 68 func (e *DockerEnv) RunTest(task Task) { 69 cmdLine := "/cdc " + task.GetCDCProfile().String() 70 bytes, err := e.ExecInController(cmdLine) 71 if err != nil { 72 log.Fatal("RunTest failed: cannot setup changefeed", 73 zap.Error(err), 74 zap.ByteString("stdout", bytes), 75 zap.ByteString("stderr", err.(*exec.ExitError).Stderr)) 76 } 77 78 upstream, err := sql.Open("mysql", UpstreamDSN) 79 if err != nil { 80 log.Fatal("RunTest: cannot connect to upstream database", zap.Error(err)) 81 } 82 83 downstream, err := sql.Open("mysql", DownstreamDSN) 84 if err != nil { 85 log.Fatal("RunTest: cannot connect to downstream database", zap.Error(err)) 86 } 87 88 taskCtx := &TaskContext{ 89 Upstream: upstream, 90 Downstream: downstream, 91 Env: e, 92 WaitForReady: func() error { 93 return retry.Do(context.Background(), e.HealthChecker, retry.WithBackoffBaseDelay(1000), retry.WithMaxTries(120), retry.WithIsRetryableErr(cerrors.IsRetryableError)) 94 }, 95 Ctx: context.Background(), 96 } 97 98 err = task.Prepare(taskCtx) 99 if err != nil { 100 e.TearDown() 101 log.Fatal("RunTest: task preparation failed", zap.String("name", task.Name()), zap.Error(err)) 102 } 103 104 log.Info("Start running task", zap.String("name", task.Name())) 105 err = task.Run(taskCtx) 106 if err != nil { 107 err1 := e.DumpStdout() 108 if err1 != nil { 109 log.Warn("Failed to dump container logs", zap.Error(err1)) 110 } 111 e.TearDown() 112 log.Fatal("RunTest: task failed", zap.String("name", task.Name()), zap.Error(err)) 113 } 114 log.Info("Finished running task", zap.String("name", task.Name())) 115 } 116 117 // SetListener implements Environment. Currently unfinished, will be used to monitor Kafka output 118 func (e *DockerEnv) SetListener(states interface{}, listener MqListener) { 119 // TODO 120 } 121 122 var systemSchema = map[string]struct{}{ 123 "INFORMATION_SCHEMA": {}, 124 "METRICS_SCHEMA": {}, 125 "PERFORMANCE_SCHEMA": {}, 126 "mysql": {}, 127 } 128 129 func dropAllSchemas(db *sql.DB) error { 130 result, err := db.Query("show databases;") 131 if err != nil { 132 return err 133 } 134 var schemaNames []string 135 var schema string 136 for result.Next() { 137 err := result.Scan(&schema) 138 if err != nil { 139 return err 140 } 141 schemaNames = append(schemaNames, schema) 142 } 143 for _, schema := range schemaNames { 144 if _, ok := systemSchema[schema]; ok { 145 continue 146 } 147 _, err := db.Exec(fmt.Sprintf("drop database %s;", schema)) 148 if err != nil { 149 return err 150 } 151 } 152 return nil 153 }