github.com/pingcap/tiup@v1.15.1/components/dm/spec/topology_dm_test.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 spec
    15  
    16  import (
    17  	"fmt"
    18  	"os"
    19  	"testing"
    20  
    21  	. "github.com/pingcap/check"
    22  	"github.com/pingcap/tiup/pkg/cluster/spec"
    23  	"github.com/stretchr/testify/assert"
    24  	"gopkg.in/yaml.v2"
    25  )
    26  
    27  type metaSuiteDM struct {
    28  }
    29  
    30  var _ = Suite(&metaSuiteDM{})
    31  
    32  func TestDefaultDataDir(t *testing.T) {
    33  	// Test with without global DataDir.
    34  	topo := new(Specification)
    35  	topo.Masters = append(topo.Masters, &MasterSpec{Host: "1.1.1.1", Port: 1111})
    36  	topo.Workers = append(topo.Workers, &WorkerSpec{Host: "1.1.2.1", Port: 2221})
    37  	data, err := yaml.Marshal(topo)
    38  	assert.Nil(t, err)
    39  
    40  	// Check default value.
    41  	topo = new(Specification)
    42  	err = yaml.Unmarshal(data, topo)
    43  	assert.Nil(t, err)
    44  	assert.Equal(t, "data", topo.GlobalOptions.DataDir)
    45  	assert.Equal(t, "data", topo.Masters[0].DataDir)
    46  	assert.Equal(t, "data", topo.Workers[0].DataDir)
    47  
    48  	// Can keep the default value.
    49  	data, err = yaml.Marshal(topo)
    50  	assert.Nil(t, err)
    51  	topo = new(Specification)
    52  	err = yaml.Unmarshal(data, topo)
    53  	assert.Nil(t, err)
    54  	assert.Equal(t, "data", topo.GlobalOptions.DataDir)
    55  	assert.Equal(t, "data", topo.Masters[0].DataDir)
    56  	assert.Equal(t, "data", topo.Workers[0].DataDir)
    57  
    58  	// Test with global DataDir.
    59  	topo = new(Specification)
    60  	topo.GlobalOptions.DataDir = "/gloable_data"
    61  	topo.Masters = append(topo.Masters, &MasterSpec{Host: "1.1.1.1", Port: 1111})
    62  	topo.Masters = append(topo.Masters, &MasterSpec{Host: "1.1.1.2", Port: 1112, DataDir: "/my_data"})
    63  	topo.Workers = append(topo.Workers, &WorkerSpec{Host: "1.1.2.1", Port: 2221})
    64  	topo.Workers = append(topo.Workers, &WorkerSpec{Host: "1.1.2.2", Port: 2222, DataDir: "/my_data"})
    65  	data, err = yaml.Marshal(topo)
    66  	assert.Nil(t, err)
    67  
    68  	topo = new(Specification)
    69  	err = yaml.Unmarshal(data, topo)
    70  
    71  	assert.Nil(t, err)
    72  	assert.Equal(t, "/gloable_data", topo.GlobalOptions.DataDir)
    73  	assert.Equal(t, "/gloable_data/dm-master-1111", topo.Masters[0].DataDir)
    74  	assert.Equal(t, "/my_data", topo.Masters[1].DataDir)
    75  	assert.Equal(t, "/gloable_data/dm-worker-2221", topo.Workers[0].DataDir)
    76  	assert.Equal(t, "/my_data", topo.Workers[1].DataDir)
    77  }
    78  
    79  func TestGlobalOptions(t *testing.T) {
    80  	topo := Specification{}
    81  	err := yaml.Unmarshal([]byte(`
    82  global:
    83    user: "test1"
    84    ssh_port: 220
    85    deploy_dir: "test-deploy"
    86    data_dir: "test-data"
    87  master_servers:
    88    - host: 172.16.5.138
    89      deploy_dir: "master-deploy"
    90  worker_servers:
    91    - host: 172.16.5.53
    92      data_dir: "worker-data"
    93  `), &topo)
    94  	assert.Nil(t, err)
    95  	assert.Equal(t, "test1", topo.GlobalOptions.User)
    96  
    97  	assert.Equal(t, 220, topo.GlobalOptions.SSHPort)
    98  	assert.Equal(t, 220, topo.Masters[0].SSHPort)
    99  	assert.Equal(t, "master-deploy", topo.Masters[0].DeployDir)
   100  
   101  	assert.Equal(t, 220, topo.Workers[0].SSHPort)
   102  	assert.Equal(t, "test-deploy/dm-worker-8262", topo.Workers[0].DeployDir)
   103  	assert.Equal(t, "worker-data", topo.Workers[0].DataDir)
   104  }
   105  
   106  func TestDirectoryConflicts(t *testing.T) {
   107  	topo := Specification{}
   108  	err := yaml.Unmarshal([]byte(`
   109  global:
   110    user: "test1"
   111    ssh_port: 220
   112    deploy_dir: "test-deploy"
   113    data_dir: "test-data"
   114  master_servers:
   115    - host: 172.16.5.138
   116      deploy_dir: "/test-1"
   117  worker_servers:
   118    - host: 172.16.5.138
   119      data_dir: "/test-1"
   120  `), &topo)
   121  	assert.NotNil(t, err)
   122  	assert.Equal(t, "directory conflict for '/test-1' between 'master_servers:172.16.5.138.deploy_dir' and 'worker_servers:172.16.5.138.data_dir'", err.Error())
   123  
   124  	err = yaml.Unmarshal([]byte(`
   125  global:
   126    user: "test1"
   127    ssh_port: 220
   128    deploy_dir: "test-deploy"
   129    data_dir: "/test-data"
   130  master_servers:
   131    - host: 172.16.5.138
   132      data_dir: "test-1"
   133  worker_servers:
   134    - host: 172.16.5.138
   135      data_dir: "test-1"
   136  `), &topo)
   137  	assert.Nil(t, err)
   138  }
   139  
   140  func TestPortConflicts(t *testing.T) {
   141  	topo := Specification{}
   142  	err := yaml.Unmarshal([]byte(`
   143  global:
   144    user: "test1"
   145    ssh_port: 220
   146    deploy_dir: "test-deploy"
   147    data_dir: "test-data"
   148  master_servers:
   149    - host: 172.16.5.138
   150      peer_port: 1234
   151  worker_servers:
   152    - host: 172.16.5.138
   153      port: 1234
   154  `), &topo)
   155  	assert.NotNil(t, err)
   156  	assert.Equal(t, "port conflict for '1234' between 'master_servers:172.16.5.138.peer_port,omitempty' and 'worker_servers:172.16.5.138.port,omitempty'", err.Error())
   157  }
   158  
   159  func TestPlatformConflicts(t *testing.T) {
   160  	// aarch64 and arm64 are equal
   161  	topo := Specification{}
   162  	err := yaml.Unmarshal([]byte(`
   163  global:
   164    os: "linux"
   165    arch: "aarch64"
   166  master_servers:
   167    - host: 172.16.5.138
   168      arch: "arm64"
   169  worker_servers:
   170    - host: 172.16.5.138
   171      arch: "aarch64"
   172  `), &topo)
   173  	assert.Nil(t, err)
   174  
   175  	// different arch defined for the same host
   176  	topo = Specification{}
   177  	err = yaml.Unmarshal([]byte(`
   178  global:
   179    os: "linux"
   180  master_servers:
   181    - host: 172.16.5.138
   182      arch: "aarch64"
   183      os: "linux"
   184  worker_servers:
   185    - host: 172.16.5.138
   186      arch: "amd64"
   187      os: "linux"
   188  `), &topo)
   189  	assert.NotNil(t, err)
   190  	assert.Equal(t, "platform mismatch for '172.16.5.138' between 'master_servers:linux/arm64' and 'worker_servers:linux/amd64'", err.Error())
   191  
   192  	// different os defined for the same host
   193  	topo = Specification{}
   194  	err = yaml.Unmarshal([]byte(`
   195  global:
   196    os: "linux"
   197    arch: "aarch64"
   198  master_servers:
   199    - host: 172.16.5.138
   200      os: "darwin"
   201      arch: "aarch64"
   202  worker_servers:
   203    - host: 172.16.5.138
   204      os: "linux"
   205      arch: "aarch64"
   206  `), &topo)
   207  	assert.NotNil(t, err)
   208  	assert.Equal(t, "platform mismatch for '172.16.5.138' between 'master_servers:darwin/arm64' and 'worker_servers:linux/arm64'", err.Error())
   209  }
   210  
   211  func TestCountDir(t *testing.T) {
   212  	topo := Specification{}
   213  
   214  	err := yaml.Unmarshal([]byte(`
   215  global:
   216    user: "test1"
   217    ssh_port: 220
   218    deploy_dir: "test-deploy"
   219  master_servers:
   220    - host: 172.16.5.138
   221      deploy_dir: "master-deploy"
   222      data_dir: "/test-data/data-1"
   223  worker_servers:
   224    - host: 172.16.5.53
   225      data_dir: "test-1"
   226  `), &topo)
   227  	assert.Nil(t, err)
   228  	cnt := topo.CountDir("172.16.5.53", "test-deploy/dm-worker-8262")
   229  	assert.Equal(t, 3, cnt)
   230  	cnt = topo.CountDir("172.16.5.138", "/test-data/data")
   231  	assert.Equal(t, 0, cnt) // should not match partial path
   232  
   233  	err = yaml.Unmarshal([]byte(`
   234  global:
   235    user: "test1"
   236    ssh_port: 220
   237    deploy_dir: "/test-deploy"
   238  master_servers:
   239    - host: 172.16.5.138
   240      deploy_dir: "master-deploy"
   241      data_dir: "/test-data/data-1"
   242  worker_servers:
   243    - host: 172.16.5.138
   244      data_dir: "/test-data/data-2"
   245  `), &topo)
   246  	assert.Nil(t, err)
   247  	cnt = topo.CountDir("172.16.5.138", "/test-deploy/dm-worker-8262")
   248  	assert.Equal(t, 2, cnt)
   249  	cnt = topo.CountDir("172.16.5.138", "")
   250  	assert.Equal(t, 2, cnt)
   251  	cnt = topo.CountDir("172.16.5.138", "test-data")
   252  	assert.Equal(t, 0, cnt)
   253  	cnt = topo.CountDir("172.16.5.138", "/test-data")
   254  	assert.Equal(t, 2, cnt)
   255  
   256  	err = yaml.Unmarshal([]byte(`
   257  global:
   258    user: "test1"
   259    ssh_port: 220
   260    deploy_dir: "/test-deploy"
   261    data_dir: "/test-data"
   262  master_servers:
   263    - host: 172.16.5.138
   264      data_dir: "data-1"
   265  worker_servers:
   266    - host: 172.16.5.138
   267      data_dir: "data-2"
   268    - host: 172.16.5.53
   269  `), &topo)
   270  	assert.Nil(t, err)
   271  	// if per-instance data_dir is set, the global data_dir is ignored, and if it
   272  	// is a relative path, it will be under the instance's deploy_dir
   273  	cnt = topo.CountDir("172.16.5.138", "/test-deploy/dm-worker-8262")
   274  	assert.Equal(t, 3, cnt)
   275  	cnt = topo.CountDir("172.16.5.138", "")
   276  	assert.Equal(t, 0, cnt)
   277  	cnt = topo.CountDir("172.16.5.53", "/test-data")
   278  	assert.Equal(t, 1, cnt)
   279  }
   280  
   281  func withTempFile(content string, fn func(string)) {
   282  	file, err := os.CreateTemp("/tmp", "topology-test")
   283  	if err != nil {
   284  		panic(fmt.Sprintf("create temp file: %s", err))
   285  	}
   286  	defer os.Remove(file.Name())
   287  
   288  	_, err = file.WriteString(content)
   289  	if err != nil {
   290  		panic(fmt.Sprintf("write temp file: %s", err))
   291  	}
   292  	file.Close()
   293  
   294  	fn(file.Name())
   295  }
   296  
   297  func with2TempFile(content1, content2 string, fn func(string, string)) {
   298  	withTempFile(content1, func(file1 string) {
   299  		withTempFile(content2, func(file2 string) {
   300  			fn(file1, file2)
   301  		})
   302  	})
   303  }
   304  
   305  func merge4test(base, scale string) (*Specification, error) {
   306  	baseTopo := Specification{}
   307  	if err := spec.ParseTopologyYaml(base, &baseTopo); err != nil {
   308  		return nil, err
   309  	}
   310  
   311  	scaleTopo := baseTopo.NewPart()
   312  	if err := spec.ParseTopologyYaml(scale, scaleTopo); err != nil {
   313  		return nil, err
   314  	}
   315  
   316  	mergedTopo := baseTopo.MergeTopo(scaleTopo)
   317  	if err := mergedTopo.Validate(); err != nil {
   318  		return nil, err
   319  	}
   320  
   321  	return mergedTopo.(*Specification), nil
   322  }
   323  
   324  func TestRelativePath(t *testing.T) {
   325  	// base test
   326  	withTempFile(`
   327  master_servers:
   328    - host: 172.16.5.140
   329  worker_servers:
   330    - host: 172.16.5.140
   331  `, func(file string) {
   332  		topo := Specification{}
   333  		err := spec.ParseTopologyYaml(file, &topo)
   334  		assert.Nil(t, err)
   335  		spec.ExpandRelativeDir(&topo)
   336  		assert.Equal(t, "/home/tidb/deploy/dm-master-8261", topo.Masters[0].DeployDir)
   337  		assert.Equal(t, "/home/tidb/deploy/dm-worker-8262", topo.Workers[0].DeployDir)
   338  	})
   339  
   340  	// test data dir & log dir
   341  	withTempFile(`
   342  master_servers:
   343    - host: 172.16.5.140
   344      deploy_dir: my-deploy
   345      data_dir: my-data
   346      log_dir: my-log
   347  `, func(file string) {
   348  		topo := Specification{}
   349  		err := spec.ParseTopologyYaml(file, &topo)
   350  		assert.Nil(t, err)
   351  		spec.ExpandRelativeDir(&topo)
   352  
   353  		assert.Equal(t, "/home/tidb/my-deploy", topo.Masters[0].DeployDir)
   354  		assert.Equal(t, "/home/tidb/my-deploy/my-data", topo.Masters[0].DataDir)
   355  		assert.Equal(t, "/home/tidb/my-deploy/my-log", topo.Masters[0].LogDir)
   356  	})
   357  
   358  	// test global options, case 1
   359  	withTempFile(`
   360  global:
   361    deploy_dir: my-deploy
   362  master_servers:
   363    - host: 172.16.5.140
   364  `, func(file string) {
   365  		topo := Specification{}
   366  		err := spec.ParseTopologyYaml(file, &topo)
   367  		assert.Nil(t, err)
   368  		spec.ExpandRelativeDir(&topo)
   369  
   370  		assert.Equal(t, "/home/tidb/my-deploy/dm-master-8261", topo.Masters[0].DeployDir)
   371  		assert.Equal(t, "/home/tidb/my-deploy/dm-master-8261/data", topo.Masters[0].DataDir)
   372  		assert.Equal(t, "", topo.Masters[0].LogDir)
   373  	})
   374  
   375  	// test global options, case 2
   376  	withTempFile(`
   377  global:
   378    deploy_dir: my-deploy
   379  master_servers:
   380    - host: 172.16.5.140
   381  worker_servers:
   382    - host: 172.16.5.140
   383      port: 20160
   384    - host: 172.16.5.140
   385      port: 20161
   386  `, func(file string) {
   387  		topo := Specification{}
   388  		err := spec.ParseTopologyYaml(file, &topo)
   389  		assert.Nil(t, err)
   390  		spec.ExpandRelativeDir(&topo)
   391  
   392  		assert.Equal(t, "my-deploy", topo.GlobalOptions.DeployDir)
   393  		assert.Equal(t, "data", topo.GlobalOptions.DataDir)
   394  
   395  		assert.Equal(t, "/home/tidb/my-deploy/dm-worker-20160", topo.Workers[0].DeployDir)
   396  		assert.Equal(t, "/home/tidb/my-deploy/dm-worker-20160/data", topo.Workers[0].DataDir)
   397  
   398  		assert.Equal(t, "/home/tidb/my-deploy/dm-worker-20161", topo.Workers[1].DeployDir)
   399  		assert.Equal(t, "/home/tidb/my-deploy/dm-worker-20161/data", topo.Workers[1].DataDir)
   400  	})
   401  
   402  	// test global options, case 3
   403  	withTempFile(`
   404  global:
   405    deploy_dir: my-deploy
   406  master_servers:
   407    - host: 172.16.5.140
   408  worker_servers:
   409    - host: 172.16.5.140
   410      port: 20160
   411      data_dir: my-data
   412      log_dir: my-log
   413    - host: 172.16.5.140
   414      port: 20161
   415  `, func(file string) {
   416  		topo := Specification{}
   417  		err := spec.ParseTopologyYaml(file, &topo)
   418  		assert.Nil(t, err)
   419  		spec.ExpandRelativeDir(&topo)
   420  
   421  		assert.Equal(t, "my-deploy", topo.GlobalOptions.DeployDir)
   422  		assert.Equal(t, "data", topo.GlobalOptions.DataDir)
   423  
   424  		assert.Equal(t, "/home/tidb/my-deploy/dm-worker-20160", topo.Workers[0].DeployDir)
   425  		assert.Equal(t, "/home/tidb/my-deploy/dm-worker-20160/my-data", topo.Workers[0].DataDir)
   426  		assert.Equal(t, "/home/tidb/my-deploy/dm-worker-20160/my-log", topo.Workers[0].LogDir)
   427  
   428  		assert.Equal(t, "/home/tidb/my-deploy/dm-worker-20161", topo.Workers[1].DeployDir)
   429  		assert.Equal(t, "/home/tidb/my-deploy/dm-worker-20161/data", topo.Workers[1].DataDir)
   430  		assert.Equal(t, "", topo.Workers[1].LogDir)
   431  	})
   432  
   433  	// test global options, case 4
   434  	withTempFile(`
   435  global:
   436    data_dir: my-global-data
   437    log_dir: my-global-log
   438  master_servers:
   439    - host: 172.16.5.140
   440  worker_servers:
   441    - host: 172.16.5.140
   442      port: 20160
   443      data_dir: my-local-data
   444      log_dir: my-local-log
   445    - host: 172.16.5.140
   446      port: 20161
   447  `, func(file string) {
   448  		topo := Specification{}
   449  		err := spec.ParseTopologyYaml(file, &topo)
   450  		assert.Nil(t, err)
   451  		spec.ExpandRelativeDir(&topo)
   452  
   453  		assert.Equal(t, "deploy", topo.GlobalOptions.DeployDir)
   454  		assert.Equal(t, "my-global-data", topo.GlobalOptions.DataDir)
   455  		assert.Equal(t, "my-global-log", topo.GlobalOptions.LogDir)
   456  
   457  		assert.Equal(t, "/home/tidb/deploy/dm-worker-20160", topo.Workers[0].DeployDir)
   458  		assert.Equal(t, "/home/tidb/deploy/dm-worker-20160/my-local-data", topo.Workers[0].DataDir)
   459  		assert.Equal(t, "/home/tidb/deploy/dm-worker-20160/my-local-log", topo.Workers[0].LogDir)
   460  
   461  		assert.Equal(t, "/home/tidb/deploy/dm-worker-20161", topo.Workers[1].DeployDir)
   462  		assert.Equal(t, "/home/tidb/deploy/dm-worker-20161/my-global-data", topo.Workers[1].DataDir)
   463  		assert.Equal(t, "/home/tidb/deploy/dm-worker-20161/my-global-log", topo.Workers[1].LogDir)
   464  	})
   465  }
   466  
   467  func TestTopologyMerge(t *testing.T) {
   468  	// base test
   469  	with2TempFile(`
   470  master_servers:
   471    - host: 172.16.5.140
   472  worker_servers:
   473    - host: 172.16.5.140
   474  `, `
   475  worker_servers:
   476    - host: 172.16.5.139
   477  `, func(base, scale string) {
   478  		topo, err := merge4test(base, scale)
   479  		assert.Nil(t, err)
   480  		spec.ExpandRelativeDir(topo)
   481  
   482  		assert.Equal(t, "/home/tidb/deploy/dm-worker-8262", topo.Workers[0].DeployDir)
   483  		assert.Equal(t, "/home/tidb/deploy/dm-worker-8262/data", topo.Workers[0].DataDir)
   484  		assert.Equal(t, "", topo.Workers[0].LogDir)
   485  
   486  		assert.Equal(t, "/home/tidb/deploy/dm-worker-8262", topo.Workers[1].DeployDir)
   487  		assert.Equal(t, "/home/tidb/deploy/dm-worker-8262/data", topo.Workers[1].DataDir)
   488  		assert.Equal(t, "", topo.Workers[1].LogDir)
   489  	})
   490  
   491  	// test global option overwrite
   492  	with2TempFile(`
   493  global:
   494    user: test
   495    deploy_dir: /my-global-deploy
   496  master_servers:
   497    - host: 172.16.5.140
   498  worker_servers:
   499    - host: 172.16.5.140
   500      log_dir: my-local-log
   501      data_dir: my-local-data
   502    - host: 172.16.5.175
   503      deploy_dir: flash-deploy
   504    - host: 172.16.5.141
   505  `, `
   506  worker_servers:
   507    - host: 172.16.5.139
   508      deploy_dir: flash-deploy
   509    - host: 172.16.5.134
   510  `, func(base, scale string) {
   511  		topo, err := merge4test(base, scale)
   512  		assert.Nil(t, err)
   513  
   514  		spec.ExpandRelativeDir(topo)
   515  
   516  		assert.Equal(t, "/my-global-deploy/dm-worker-8262", topo.Workers[0].DeployDir)
   517  		assert.Equal(t, "/my-global-deploy/dm-worker-8262/my-local-data", topo.Workers[0].DataDir)
   518  		assert.Equal(t, "/my-global-deploy/dm-worker-8262/my-local-log", topo.Workers[0].LogDir)
   519  
   520  		assert.Equal(t, "/home/test/flash-deploy", topo.Workers[1].DeployDir)
   521  		assert.Equal(t, "/home/test/flash-deploy/data", topo.Workers[1].DataDir)
   522  		assert.Equal(t, "/home/test/flash-deploy", topo.Workers[3].DeployDir)
   523  		assert.Equal(t, "/home/test/flash-deploy/data", topo.Workers[3].DataDir)
   524  
   525  		assert.Equal(t, "/my-global-deploy/dm-worker-8262", topo.Workers[2].DeployDir)
   526  		assert.Equal(t, "/my-global-deploy/dm-worker-8262/data", topo.Workers[2].DataDir)
   527  		assert.Equal(t, "/my-global-deploy/dm-worker-8262", topo.Workers[4].DeployDir)
   528  		assert.Equal(t, "/my-global-deploy/dm-worker-8262/data", topo.Workers[4].DataDir)
   529  	})
   530  }
   531  
   532  func TestMonitorLogDir(t *testing.T) {
   533  	withTempFile(`
   534  monitored:
   535    node_exporter_port: 39100
   536    blackbox_exporter_port: 39115
   537    deploy_dir: "test-deploy"
   538    log_dir: "test-deploy/log"
   539  `, func(file string) {
   540  		topo := Specification{}
   541  		err := spec.ParseTopologyYaml(file, &topo)
   542  		assert.Nil(t, err)
   543  		assert.Equal(t, 39100, topo.MonitoredOptions.NodeExporterPort)
   544  		assert.Equal(t, 39115, topo.MonitoredOptions.BlackboxExporterPort)
   545  		assert.Equal(t, "test-deploy/log", topo.MonitoredOptions.LogDir)
   546  		assert.Equal(t, "test-deploy", topo.MonitoredOptions.DeployDir)
   547  	})
   548  }