github.com/pingcap/ticdc@v0.0.0-20220526033649-485a10ef2652/integration/framework/avro/kafka_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 avro
    15  
    16  import (
    17  	"encoding/json"
    18  	"io/ioutil"
    19  	"net/http"
    20  	"path"
    21  
    22  	"github.com/integralist/go-findroot/find"
    23  	"github.com/pingcap/errors"
    24  	"github.com/pingcap/log"
    25  	"github.com/pingcap/ticdc/integration/framework"
    26  	"go.uber.org/zap"
    27  )
    28  
    29  const (
    30  	healthCheckURI          = "http://127.0.0.1:18083"
    31  	dockerComposeFilePath   = "/docker-compose-avro.yml"
    32  	controllerContainerName = "ticdc_controller_1"
    33  )
    34  
    35  // KafkaDockerEnv represents the docker-compose service defined in docker-compose-avro.yml
    36  type KafkaDockerEnv struct {
    37  	framework.DockerEnv
    38  }
    39  
    40  // NewKafkaDockerEnv creates a new KafkaDockerEnv
    41  func NewKafkaDockerEnv(dockerComposeFile string) *KafkaDockerEnv {
    42  	healthChecker := func() error {
    43  		resp, err := http.Get(healthCheckURI)
    44  		if err != nil {
    45  			return err
    46  		}
    47  
    48  		if resp.Body == nil {
    49  			return errors.New("kafka Connect HealthCheck returns empty body")
    50  		}
    51  		defer func() { _ = resp.Body.Close() }()
    52  
    53  		bytes, err := ioutil.ReadAll(resp.Body)
    54  		if err != nil {
    55  			return err
    56  		}
    57  
    58  		m := make(map[string]interface{})
    59  		err = json.Unmarshal(bytes, &m)
    60  		if err != nil {
    61  			return err
    62  		}
    63  
    64  		healthy, ok := m["healthy"]
    65  		if !ok {
    66  			return errors.New("kafka connect healthcheck did not return health info")
    67  		}
    68  
    69  		if v, ok := healthy.(bool); !ok || !v {
    70  			return errors.New("kafka connect not healthy")
    71  		}
    72  
    73  		return nil
    74  	}
    75  
    76  	var file string
    77  	if dockerComposeFile == "" {
    78  		st, err := find.Repo()
    79  		if err != nil {
    80  			log.Fatal("Could not find git repo root", zap.Error(err))
    81  		}
    82  		file = path.Join(st.Path, dockerComposeFilePath)
    83  	} else {
    84  		file = dockerComposeFile
    85  	}
    86  
    87  	return &KafkaDockerEnv{DockerEnv: framework.DockerEnv{
    88  		DockerComposeOperator: framework.DockerComposeOperator{
    89  			FileName:      file,
    90  			Controller:    controllerContainerName,
    91  			HealthChecker: healthChecker,
    92  		},
    93  	}}
    94  }
    95  
    96  // Setup brings up a docker-compose service
    97  func (d *KafkaDockerEnv) Setup() {
    98  	d.DockerEnv.Setup()
    99  	if err := createConnector(); err != nil {
   100  		log.Fatal("failed to create connector", zap.Error(err))
   101  	}
   102  }
   103  
   104  // Reset implements Environment
   105  func (d *KafkaDockerEnv) Reset() {
   106  	d.DockerEnv.Reset()
   107  	if err := d.resetSchemaRegistry(); err != nil {
   108  		log.Fatal("failed to reset schema registry", zap.Error(err))
   109  	}
   110  	if err := d.resetKafkaConnector(); err != nil {
   111  		log.Fatal("failed to reset kafka connector", zap.Error(err))
   112  	}
   113  }
   114  
   115  func (d *KafkaDockerEnv) resetSchemaRegistry() error {
   116  	resp, err := http.Get("http://127.0.0.1:8081/subjects")
   117  	if err != nil {
   118  		return err
   119  	}
   120  	if resp.Body == nil {
   121  		return errors.New("get schema registry subjects returns empty body")
   122  	}
   123  	defer resp.Body.Close()
   124  
   125  	bytes, err := ioutil.ReadAll(resp.Body)
   126  	if err != nil {
   127  		return err
   128  	}
   129  
   130  	subs := []string{}
   131  	err = json.Unmarshal(bytes, &subs)
   132  	if err != nil {
   133  		return err
   134  	}
   135  	for _, sub := range subs {
   136  		url := "http://127.0.0.1:8081/subjects/" + sub
   137  		req, err := http.NewRequest(http.MethodDelete, url, nil)
   138  		if err != nil {
   139  			return err
   140  		}
   141  		res, err := http.DefaultClient.Do(req)
   142  		if err != nil {
   143  			return err
   144  		}
   145  		defer res.Body.Close()
   146  	}
   147  	log.Info("Deleted the schema registry subjects", zap.Any("subjects", subs))
   148  	return nil
   149  }
   150  
   151  func (d *KafkaDockerEnv) resetKafkaConnector() error {
   152  	url := "http://127.0.0.1:8083/connectors/jdbc-sink-connector/"
   153  	req, err := http.NewRequest(http.MethodDelete, url, nil)
   154  	if err != nil {
   155  		return err
   156  	}
   157  	res, err := http.DefaultClient.Do(req)
   158  	if err != nil {
   159  		return err
   160  	}
   161  	defer res.Body.Close()
   162  	return createConnector()
   163  }