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