github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/tests/openapi/client/openapi_task_check (about)

     1  #!/usr/bin/env python
     2  # -*- coding: utf-8 -*-
     3  import sys
     4  import requests
     5  
     6  SHARD_TASK_NAME = "test-shard"
     7  ILLEGAL_CHAR_TASK_NAME = "t-Ë!s`t"
     8  SOURCE1_NAME = "mysql-01"
     9  SOURCE2_NAME = "mysql-02"
    10  
    11  
    12  API_ENDPOINT = "http://127.0.0.1:8361/api/v1/tasks"
    13  
    14  
    15  def create_task_failed():
    16      task = {
    17          "name": "test",
    18          "task_mode": "all",
    19          "shard_mode": "pessimistic_xxd",  # pessimistic_xxd is not a valid shard mode
    20          "meta_schema": "dm-meta",
    21          "enhance_online_schema_change": True,
    22          "on_duplicate": "error",
    23          "target_config": {
    24              "host": "127.0.0.1",
    25              "port": 4000,
    26              "user": "root",
    27              "password": "",
    28          },
    29          "table_migrate_rule": [
    30              {
    31                  "source": {
    32                      "source_name": SOURCE1_NAME,
    33                      "schema": "openapi",
    34                      "table": "*",
    35                  },
    36                  "target": {"schema": "openapi", "table": "t"},
    37              },
    38              {
    39                  "source": {
    40                      "source_name": SOURCE2_NAME,
    41                      "schema": "openapi",
    42                      "table": "*",
    43                  },
    44                  "target": {"schema": "openapi", "table": "t"},
    45              },
    46          ],
    47          "source_config": {
    48              "source_conf": [
    49                  {"source_name": SOURCE1_NAME},
    50                  {"source_name": SOURCE2_NAME},
    51              ],
    52          },
    53      }
    54      resp = requests.post(url=API_ENDPOINT, json={"task": task})
    55      print("create_task_failed resp=", resp.json())
    56      assert resp.status_code == 400
    57  
    58  def create_task_with_precheck(task_name, ignore_check, is_success, check_result):
    59      task = {
    60          "name": task_name,
    61          "task_mode": "all",
    62          "meta_schema": "dm_meta",
    63          "shard_mode": "pessimistic",
    64          "enhance_online_schema_change": True,
    65          "on_duplicate": "error",
    66          "ignore_checking_items" : ["version", ignore_check],
    67          "target_config": {
    68              "host": "127.0.0.1",
    69              "port": 4000,
    70              "user": "root",
    71              "password": "",
    72          },
    73          "table_migrate_rule": [
    74              {
    75                  "source": {
    76                      "source_name": SOURCE1_NAME,
    77                      "schema": "openapi",
    78                      "table": "t*",
    79                  },
    80                  "target": {"schema": "openapi", "table": "t"},
    81              },
    82              {
    83                  "source": {
    84                      "source_name": SOURCE2_NAME,
    85                      "schema": "openapi",
    86                      "table": "t*",
    87                  },
    88                  "target": {"schema": "openapi", "table": "t"},
    89              },
    90          ],
    91          "source_config": {
    92              "source_conf": [
    93                  {"source_name": SOURCE1_NAME},
    94                  {"source_name": SOURCE2_NAME},
    95              ],
    96          },
    97      }
    98  
    99      resp = requests.post(url=API_ENDPOINT, json={"task": task})
   100      print("create_task_with_precheck resp=", resp.json())
   101      if is_success == "success":
   102           assert resp.status_code == 201
   103           assert check_result in resp.json()["check_result"]
   104      else:
   105          assert resp.status_code == 400
   106          assert check_result in resp.json()["error_msg"]
   107  
   108  def create_noshard_task_success(task_name, tartget_table_name=""):
   109      task = {
   110          "name": task_name,
   111          "task_mode": "all",
   112          "meta_schema": "dm-meta",
   113          "enhance_online_schema_change": True,
   114          "on_duplicate": "error",
   115          "target_config": {
   116              "host": "127.0.0.1",
   117              "port": 4000,
   118              "user": "root",
   119              "password": "",
   120          },
   121          "table_migrate_rule": [
   122              {
   123                  "source": {
   124                      "source_name": SOURCE1_NAME,
   125                      "schema": "openapi",
   126                      "table": "*",
   127                  },
   128                  "target": {"schema": "openapi", "table": tartget_table_name},
   129              },
   130              {
   131                  "source": {
   132                      "source_name": SOURCE2_NAME,
   133                      "schema": "openapi",
   134                      "table": "*",
   135                  },
   136                  "target": {"schema": "openapi", "table": tartget_table_name},
   137              },
   138          ],
   139          "source_config": {
   140              "source_conf": [
   141                  {"source_name": SOURCE1_NAME},
   142                  {"source_name": SOURCE2_NAME},
   143              ],
   144          },
   145      }
   146      resp = requests.post(url=API_ENDPOINT, json={"task": task})
   147      print("create_noshard_task_success resp=", resp.json())
   148      assert resp.status_code == 201
   149  
   150  def create_incremental_task_with_gtid_success(task_name,binlog_name1,binlog_pos1,binlog_gtid1,binlog_name2,binlog_pos2,binlog_gtid2):
   151      task = {
   152          "name": task_name,
   153          "task_mode": "incremental",
   154          "meta_schema": "dm_meta",
   155          "enhance_online_schema_change": True,
   156          "on_duplicate": "error",
   157          "target_config": {
   158              "host": "127.0.0.1",
   159              "port": 4000,
   160              "user": "root",
   161              "password": "",
   162          },
   163          "table_migrate_rule": [
   164              {
   165                  "source": {
   166                      "source_name": SOURCE1_NAME,
   167                      "schema": "openapi",
   168                      "table": "*",
   169                  },
   170                  "target": {"schema": "openapi", "table": ""},
   171              },
   172              {
   173                  "source": {
   174                      "source_name": SOURCE2_NAME,
   175                      "schema": "openapi",
   176                      "table": "*",
   177                  },
   178                  "target": {"schema": "openapi", "table": ""},
   179              },
   180          ],
   181           "source_config": {
   182              "source_conf": [
   183                  {"source_name": SOURCE1_NAME},
   184                  {"source_name": SOURCE2_NAME},
   185              ],
   186           },
   187      }
   188  
   189      if binlog_pos1 != "":
   190          task["source_config"] = {
   191              "source_conf": [
   192                  {
   193                      "source_name": SOURCE1_NAME,
   194                      "binlog_name": binlog_name1,
   195                      "binlog_pos": int(binlog_pos1),
   196                      "binlog_gtid": binlog_gtid1,
   197                  },
   198                  {
   199                      "source_name": SOURCE2_NAME,
   200                      "binlog_name": binlog_name2,
   201                      "binlog_pos": int(binlog_pos2),
   202                      "binlog_gtid": binlog_gtid2,
   203                  },
   204              ],
   205          }
   206  
   207      resp = requests.post(url=API_ENDPOINT, json={"task": task})
   208      print("create_incremental_task_with_gtid_success resp=", resp.json())
   209      assert resp.status_code == 201
   210  
   211  def create_shard_task_success():
   212      task = {
   213          "name": SHARD_TASK_NAME,
   214          "task_mode": "all",
   215          "shard_mode": "pessimistic",
   216          "meta_schema": "dm-meta",
   217          "enhance_online_schema_change": True,
   218          "on_duplicate": "error",
   219          "target_config": {
   220              "host": "127.0.0.1",
   221              "port": 4000,
   222              "user": "root",
   223              "password": "",
   224          },
   225          "table_migrate_rule": [
   226              {
   227                  "source": {
   228                      "source_name": SOURCE1_NAME,
   229                      "schema": "openapi",
   230                      "table": "*",
   231                  },
   232                  "target": {"schema": "openapi", "table": "t"},
   233                  "binlog_filter_rule": ["rule-1"],
   234              },
   235              {
   236                  "source": {
   237                      "source_name": SOURCE2_NAME,
   238                      "schema": "openapi",
   239                      "table": "*",
   240                  },
   241                  "target": {"schema": "openapi", "table": "t"},
   242                  "binlog_filter_rule": ["rule-2"],
   243              },
   244          ],
   245          "source_config": {
   246              "full_migrate_conf": {
   247                  "export_threads": 4,
   248                  "import_threads": 16,
   249                  "data_dir": "./exported_data",
   250                  "consistency": "auto",
   251              },
   252              "incr_migrate_conf": {"repl_threads": 16, "repl_batch": 100},
   253              "source_conf": [
   254                  {"source_name": SOURCE1_NAME},
   255                  {"source_name": SOURCE2_NAME},
   256              ],
   257          },
   258          "binlog_filter_rule": {
   259              "rule-1": {
   260                  "ignore_event": ["delete"],
   261              },
   262              "rule-2": {
   263                  "ignore_sql": ["alter table openapi.t add column aaa int;"],
   264              },
   265          },
   266      }
   267      resp = requests.post(url=API_ENDPOINT, json={"task": task})
   268      print("create_shard_task_success resp=", resp.json())
   269      assert resp.status_code == 201
   270  
   271  
   272  def start_task_success(task_name, source_name):
   273      url = API_ENDPOINT + "/" + task_name + "/start"
   274      req = {}
   275      if source_name != "":
   276          req = {"source_name_list": [source_name], "remove_meta": True}
   277      resp = requests.post(url=url, json=req)
   278      if resp.status_code != 200:
   279          print("start_task_failed resp=", resp.json())
   280      assert resp.status_code == 200
   281  
   282  def start_task_failed(task_name, source_name, check_result):
   283      url = API_ENDPOINT + "/" + task_name + "/start"
   284      req = {}
   285      if source_name != "":
   286          req = {"source_name_list": [source_name], "remove_meta": True}
   287      resp = requests.post(url=url, json=req)
   288      if resp.status_code == 200:
   289           print("start_task_failed resp should not be 200")
   290      assert resp.status_code == 400
   291      print("start_task_failed resp=", resp.json())
   292      assert check_result in resp.json()["error_msg"]
   293  
   294  def start_task_with_condition(task_name, start_time, duration, is_success, check_result):
   295      url = API_ENDPOINT + "/" + task_name + "/start"
   296      req = {"start_time": start_time, "safe_mode_time_duration": duration}
   297      resp = requests.post(url=url, json=req)
   298      if is_success == "success":
   299          if resp.status_code != 200:
   300              print("start_task_with_condition_failed resp=", resp.json())
   301          assert resp.status_code == 200
   302          print("start_task_with_condition success")
   303      else:
   304          if resp.status_code == 200:
   305               print("start_task_with_condition_failed resp should not be 200")
   306          assert resp.status_code == 400
   307          print("start_task_with_condition resp=", resp.json())
   308          assert check_result in resp.json()["error_msg"]
   309  
   310  def stop_task_with_condition(task_name, source_name, timeout_duration):
   311      url = API_ENDPOINT + "/" + task_name + "/stop"
   312      req = {"timeout_duration": timeout_duration}
   313      if source_name != "":
   314          req = {"source_name_list": [source_name], "timeout_duration": timeout_duration}
   315      resp = requests.post(url=url, json=req)
   316      if resp.status_code != 200:
   317          print("stop_task_failed resp=", resp.json())
   318      assert resp.status_code == 200
   319  
   320  def stop_task_success(task_name, source_name):
   321      url = API_ENDPOINT + "/" + task_name + "/stop"
   322      req = {}
   323      if source_name != "":
   324          req = {"source_name_list": [source_name]}
   325      resp = requests.post(url=url, json=req)
   326      if resp.status_code != 200:
   327          print("stop_task_failed resp=", resp.json())
   328      assert resp.status_code == 200
   329  
   330  def delete_task_success(task_name):
   331      resp = requests.delete(url=API_ENDPOINT + "/" + task_name)
   332      assert resp.status_code == 204
   333      print("delete_task_success")
   334  
   335  
   336  def delete_task_failed(task_name):
   337      resp = requests.delete(url=API_ENDPOINT + "/" + task_name)
   338      print("delete_task_failed resp=", resp.json())
   339      assert resp.status_code == 400
   340  
   341  
   342  def delete_task_with_force_success(task_name):
   343      resp = requests.delete(url=API_ENDPOINT + "/" + task_name + "?force=true")
   344      assert resp.status_code == 204
   345      print("delete_task_success")
   346  
   347  
   348  def get_task_status_failed(task_name):
   349      url = API_ENDPOINT + "/" + task_name + "/status"
   350      resp = requests.get(url=url)
   351      print("get_task_status_failed resp=", resp.json())
   352      assert resp.status_code == 400
   353  
   354  
   355  def get_illegal_char_task_status_failed():
   356      # task name contains illegal char but api server can handle it.
   357      # return 400 is because of the task is not started.
   358      url = API_ENDPOINT + "/" + ILLEGAL_CHAR_TASK_NAME + "/status"
   359      resp = requests.get(url=url)
   360      print("get_illegal_char_task_status_failed resp=", resp.json())
   361      assert resp.status_code == 400
   362      if sys.version_info.major == 2:
   363          # need decode in python2
   364          assert ILLEGAL_CHAR_TASK_NAME.decode("utf-8") in resp.json()["error_msg"]
   365      else:
   366          assert ILLEGAL_CHAR_TASK_NAME in resp.json()["error_msg"]
   367  
   368  
   369  def get_task_status_success(task_name, total):
   370      url = API_ENDPOINT + "/" + task_name + "/status"
   371      resp = requests.get(url=url)
   372      data = resp.json()
   373      assert resp.status_code == 200
   374      print("get_task_status_success resp=", data)
   375      assert data["total"] == int(total)
   376  
   377  
   378  def get_task_status_success_but_worker_meet_error(task_name, total):
   379      url = API_ENDPOINT + "/" + task_name + "/status"
   380      resp = requests.get(url=url)
   381      data = resp.json()
   382      assert resp.status_code == 200
   383      print("get_task_status_success_but_worker_meet_error resp=", data)
   384      assert data["total"] == int(total)
   385      for status in data["data"]:
   386          assert status["name"] == task_name
   387          assert status["error_msg"] is not None
   388  
   389  
   390  def get_task_list(task_count):
   391      url = API_ENDPOINT
   392      resp = requests.get(url=url)
   393      data = resp.json()
   394      assert resp.status_code == 200
   395      print("get_task_list resp=", data)
   396      assert data["total"] == int(task_count)
   397  
   398  
   399  def get_task_list_with_status(task_count, task_name, status_count):
   400      url = API_ENDPOINT + "?with_status=true"
   401      resp = requests.get(url=url)
   402      data = resp.json()
   403      assert resp.status_code == 200
   404      print("get_task_list_with_status resp=", data)
   405  
   406      assert data["total"] == int(task_count)
   407      find_task = False
   408      for task in data["data"]:
   409          if task["name"] == task_name:
   410              find_task = True
   411              assert len(task["status_list"]) == int(status_count)
   412      assert find_task
   413  
   414  
   415  def operate_schema_and_table_success(task_name, source_name, schema_name, table_name):
   416      schema_url = API_ENDPOINT + "/" + task_name + "/sources/" + source_name + "/schemas"
   417      schema_resp = requests.get(url=schema_url)
   418      assert schema_resp.status_code == 200
   419      print("get_task_schema_success schema resp=", schema_resp.json())
   420      assert len(schema_resp.json()) > 0
   421  
   422      schema_list = schema_resp.json()
   423      assert schema_name in schema_list
   424      table_url = schema_url + "/" + schema_name
   425      table_resp = requests.get(url=table_url)
   426      assert table_resp.status_code == 200
   427      print("get_task_schema_success table resp=", table_resp.json())
   428      table_list = table_resp.json()
   429      assert table_name in table_list
   430  
   431      single_table_url = table_url + "/" + table_name
   432      create_table_resp = requests.get(url=single_table_url)
   433      assert create_table_resp.status_code == 200
   434      create_table = create_table_resp.json()
   435      print("get_task_schema_success create table resp=", create_table)
   436      assert create_table["table_name"] == table_name
   437      assert create_table["schema_name"] == schema_name
   438      assert table_name in create_table["schema_create_sql"]
   439  
   440      # overwrite table
   441      set_table_data = {
   442          "sql_content": "CREATE TABLE openapi.t1(i TINYINT, j INT UNIQUE KEY);",
   443          "flush": True,
   444          "sync": True,
   445      }
   446      resp = requests.put(url=single_table_url, json=set_table_data)
   447      assert resp.status_code == 200
   448      table_list = requests.get(url=table_url).json()
   449      print("get_task_schema_success table resp=", table_list)
   450      assert len(table_list) == 1
   451  
   452  
   453  def create_task_template_success(task_name, target_table_name=""):
   454      url = API_ENDPOINT + "/templates"
   455      task = {
   456          "name": task_name,
   457          "task_mode": "all",
   458          "shard_mode": "pessimistic",
   459          "meta_schema": "dm-meta",
   460          "enhance_online_schema_change": True,
   461          "on_duplicate": "error",
   462          "target_config": {
   463              "host": "127.0.0.1",
   464              "port": 4000,
   465              "user": "root",
   466              "password": "",
   467          },
   468          "table_migrate_rule": [
   469              {
   470                  "source": {
   471                      "source_name": SOURCE1_NAME,
   472                      "schema": "openapi",
   473                      "table": "*",
   474                  },
   475                  "target": {"schema": "openapi", "table": target_table_name},
   476              },
   477              {
   478                  "source": {
   479                      "source_name": SOURCE2_NAME,
   480                      "schema": "openapi",
   481                      "table": "*",
   482                  },
   483                  "target": {"schema": "openapi", "table": target_table_name},
   484              },
   485          ],
   486          "source_config": {
   487              "source_conf": [
   488                  {"source_name": SOURCE1_NAME},
   489                  {"source_name": SOURCE2_NAME},
   490              ],
   491          },
   492      }
   493      resp = requests.post(url=url, json=task)
   494      print("create_task_template_success resp=", resp.json())
   495      assert resp.status_code == 201
   496  
   497  
   498  def create_task_template_failed():
   499      url = API_ENDPOINT + "/templates"
   500      task = {
   501          "name": "test",
   502          "task_mode": "all",
   503          "shard_mode": "pessimistic_xxd",  # pessimistic_xxd is not a valid shard mode
   504          "meta_schema": "dm-meta",
   505          "enhance_online_schema_change": True,
   506          "on_duplicate": "error",
   507          "target_config": {
   508              "host": "127.0.0.1",
   509              "port": 4000,
   510              "user": "root",
   511              "password": "",
   512          },
   513          "table_migrate_rule": [
   514              {
   515                  "source": {
   516                      "source_name": SOURCE1_NAME,
   517                      "schema": "openapi",
   518                      "table": "*",
   519                  },
   520                  "target": {"schema": "openapi", "table": "t"},
   521              },
   522              {
   523                  "source": {
   524                      "source_name": SOURCE2_NAME,
   525                      "schema": "openapi",
   526                      "table": "*",
   527                  },
   528                  "target": {"schema": "openapi", "table": "t"},
   529              },
   530          ],
   531          "source_config": {
   532              "source_conf": [
   533                  {"source_name": SOURCE1_NAME},
   534                  {"source_name": SOURCE2_NAME},
   535              ],
   536          },
   537      }
   538      resp = requests.post(url=url, json=task)
   539      print("create_task_template_failed resp=", resp.json())
   540      assert resp.status_code == 400
   541  
   542  
   543  def list_task_template(count):
   544      url = API_ENDPOINT + "/templates"
   545      resp = requests.get(url=url)
   546      data = resp.json()
   547      assert resp.status_code == 200
   548      print("list_task_template resp=", data)
   549      assert data["total"] == int(count)
   550  
   551  
   552  def import_task_template(success_count, failed_count):
   553      url = API_ENDPOINT + "/templates/import"
   554      resp = requests.post(url=url)
   555      data = resp.json()
   556      print("import_task_template resp=", data)
   557      assert resp.status_code == 202
   558      assert len(data["success_task_list"]) == int(success_count)
   559      assert len(data["failed_task_list"]) == int(failed_count)
   560  
   561  
   562  def get_task_template(name):
   563      url = API_ENDPOINT + "/templates/" + name
   564      resp = requests.get(url=url)
   565      data = resp.json()
   566      assert resp.status_code == 200
   567      print("get_task_template resp=", data)
   568      assert data["name"] == name
   569  
   570  
   571  def update_task_template_success(name, task_mode):
   572      url = API_ENDPOINT + "/templates/" + name
   573  
   574      # get task template first
   575      task = requests.get(url=url).json()
   576      task["task_mode"] = task_mode
   577      resp = requests.put(url=url, json=task)
   578      print("update_task_template_success resp=", resp.json())
   579      assert resp.status_code == 200
   580  
   581      # update task template success
   582      assert requests.get(url=url).json()["task_mode"] == task_mode
   583  
   584  
   585  def delete_task_template(name):
   586      url = API_ENDPOINT + "/templates/" + name
   587      resp = requests.delete(url=url)
   588      assert resp.status_code == 204
   589      print("delete_task_template")
   590  
   591  
   592  def check_noshard_task_dump_status_success(task_name, total):
   593      url = API_ENDPOINT + "/" + task_name + "/status"
   594      resp = requests.get(url=url)
   595      data = resp.json()
   596      assert resp.status_code == 200
   597      print("check_dump_status_success resp=", data)
   598      assert data["data"][0]["dump_status"]["finished_bytes"] == int(total)
   599  
   600  
   601  def do_complex_operations(task_name):
   602      source1_url = "http://127.0.0.1:8361/api/v1/sources/" + SOURCE1_NAME
   603      task_url = "http://127.0.0.1:8361/api/v1/tasks/" + task_name
   604      enable_source_url = source1_url + "/enable"
   605      disable_source_url = source1_url + "/disable"
   606  
   607      stop_url = task_url + "/stop"
   608      start_url = task_url + "/start"
   609      status_url = task_url + "/status"
   610      migrate_targets_url = task_url + "/sources/" + SOURCE1_NAME + "/migrate_targets"
   611  
   612      # get source
   613      source = requests.get(source1_url).json()
   614      # update source failed
   615      update_source_req = {"source": source}
   616      resp = requests.put(source1_url, json=update_source_req)
   617      assert resp.status_code == 400
   618  
   619      # get task
   620      task = requests.get(task_url).json()
   621  
   622      # update task failed
   623      update_task_req = {"task": task}
   624      resp = requests.put(task_url, json=update_task_req)
   625      assert resp.status_code == 400
   626  
   627      # stop task
   628      resp = requests.post(stop_url)
   629      status = requests.get(status_url).json()
   630      for s in status["data"]:
   631          assert s["stage"] == "Paused"
   632  
   633      # update task success
   634      task["source_config"]["incr_migrate_conf"]["repl_threads"] = 1
   635      update_task_req = {"task": task}
   636      resp = requests.put(task_url, json=update_task_req)
   637      if resp.status_code != 200:
   638          print("update task failed", resp.json())
   639      assert resp.status_code == 200
   640      task_after_updated = requests.get(task_url).json()
   641      assert task_after_updated["source_config"]["incr_migrate_conf"]["repl_threads"] == 1
   642  
   643      # start again
   644      resp = requests.post(start_url)
   645      if resp.status_code != 200:
   646          print("start task failed", resp.json())
   647      assert resp.status_code == 200
   648      status = requests.get(status_url).json()
   649      for s in status["data"]:
   650          assert s["stage"] == "Running"
   651  
   652      # disable source1, subtask on source is paused
   653      resp = requests.post(disable_source_url)
   654      if resp.status_code != 200:
   655          print("disable source failed", resp.json())
   656      assert resp.status_code == 200
   657      status = requests.get(status_url).json()
   658      for s in status["data"]:
   659          if s["source_name"] == SOURCE1_NAME:
   660              assert s["stage"] == "Paused"
   661          else:
   662              assert s["stage"] == "Running"
   663  
   664      # update source1 success
   665      source["enable_gtid"] = True
   666      source["password"] = "123456"
   667      resp = requests.put(source1_url, json=update_source_req)
   668      if resp.status_code != 200:
   669          print("update source failed", resp.json())
   670      assert resp.status_code == 200
   671  
   672      # enable source task will start again
   673      resp = requests.post(enable_source_url)
   674      if resp.status_code != 200:
   675          print("enable source failed", resp.json())
   676      assert resp.status_code == 200
   677      status = requests.get(status_url).json()
   678      for s in status["data"]:
   679          assert s["stage"] == "Running"
   680  
   681      # list migrate targets
   682      source1_migrate_rules = []
   683      for rule in task["table_migrate_rule"]:
   684          if rule["source"]["source_name"] == SOURCE1_NAME:
   685              source1_migrate_rules.append(rule)
   686  
   687      resp = requests.get(migrate_targets_url)
   688      if resp.status_code != 200:
   689          print("list migrate targets failed", resp.json())
   690      assert resp.status_code == 200
   691      data = resp.json()
   692      assert data["total"] == len(source1_migrate_rules)
   693      assert (
   694          data["data"][0]["source_schema"] == source1_migrate_rules[0]["source"]["schema"]
   695      )
   696      assert (
   697          data["data"][0]["target_schema"] == source1_migrate_rules[0]["target"]["schema"]
   698      )
   699  
   700  
   701  if __name__ == "__main__":
   702      FUNC_MAP = {
   703          "create_task_failed": create_task_failed,
   704          "create_noshard_task_success": create_noshard_task_success,
   705          "create_shard_task_success": create_shard_task_success,
   706          "create_incremental_task_with_gtid_success": create_incremental_task_with_gtid_success,
   707          "delete_task_failed": delete_task_failed,
   708          "delete_task_success": delete_task_success,
   709          "delete_task_with_force_success": delete_task_with_force_success,
   710          "start_task_success": start_task_success,
   711          "start_task_failed": start_task_failed,
   712          "start_task_with_condition": start_task_with_condition,
   713          "stop_task_with_condition": stop_task_with_condition,
   714          "stop_task_success": stop_task_success,
   715          "get_task_list": get_task_list,
   716          "get_task_list_with_status": get_task_list_with_status,
   717          "get_task_status_failed": get_task_status_failed,
   718          "get_illegal_char_task_status_failed": get_illegal_char_task_status_failed,
   719          "get_task_status_success": get_task_status_success,
   720          "get_task_status_success_but_worker_meet_error": get_task_status_success_but_worker_meet_error,
   721          "operate_schema_and_table_success": operate_schema_and_table_success,
   722          "create_task_template_success": create_task_template_success,
   723          "create_task_template_failed": create_task_template_failed,
   724          "list_task_template": list_task_template,
   725          "import_task_template": import_task_template,
   726          "get_task_template": get_task_template,
   727          "update_task_template_success": update_task_template_success,
   728          "delete_task_template": delete_task_template,
   729          "check_noshard_task_dump_status_success": check_noshard_task_dump_status_success,
   730          "do_complex_operations": do_complex_operations,
   731          "create_task_with_precheck": create_task_with_precheck,
   732      }
   733  
   734      func = FUNC_MAP[sys.argv[1]]
   735      if len(sys.argv) >= 2:
   736          func(*sys.argv[2:])
   737      else:
   738          func()