github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/cmd/services/m3dbnode/config/config_test.go (about)

     1  // Copyright (c) 2017 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package config
    22  
    23  import (
    24  	"fmt"
    25  	"io/ioutil"
    26  	"os"
    27  	"testing"
    28  
    29  	"github.com/m3db/m3/src/dbnode/client"
    30  	"github.com/m3db/m3/src/dbnode/environment"
    31  	"github.com/m3db/m3/src/dbnode/storage"
    32  	"github.com/m3db/m3/src/dbnode/storage/bootstrap/bootstrapper/commitlog"
    33  	"github.com/m3db/m3/src/dbnode/storage/bootstrap/result"
    34  	"github.com/m3db/m3/src/dbnode/topology"
    35  	xconfig "github.com/m3db/m3/src/x/config"
    36  	"github.com/m3db/m3/src/x/instrument"
    37  	xtest "github.com/m3db/m3/src/x/test"
    38  
    39  	"github.com/golang/mock/gomock"
    40  	"github.com/stretchr/testify/assert"
    41  	"github.com/stretchr/testify/require"
    42  	yaml "gopkg.in/yaml.v2"
    43  )
    44  
    45  const testBaseConfig = `
    46  db:
    47    logging:
    48        level: info
    49        file: /var/log/m3dbnode.log
    50  
    51    cache:
    52        postingsList:
    53            size: 100
    54            cacheRegexp: false
    55            cacheTerms: false
    56            cacheSearch: null
    57        series:
    58            policy: lru
    59  
    60    metrics:
    61        prometheus:
    62            handlerPath: /metrics
    63        sanitization: prometheus
    64        samplingRate: 1.0
    65        extended: detailed
    66  
    67    listenAddress: 0.0.0.0:9000
    68    clusterListenAddress: 0.0.0.0:9001
    69    httpNodeListenAddress: 0.0.0.0:9002
    70    httpClusterListenAddress: 0.0.0.0:9003
    71    debugListenAddress: 0.0.0.0:9004
    72  
    73    hostID:
    74        resolver: config
    75        value: host1
    76  
    77    client:
    78        writeConsistencyLevel: majority
    79        readConsistencyLevel: unstrict_majority
    80        connectConsistencyLevel: any
    81        writeTimeout: 10s
    82        fetchTimeout: 15s
    83        connectTimeout: 20s
    84        writeRetry:
    85            initialBackoff: 500ms
    86            backoffFactor: 3
    87            maxRetries: 2
    88            jitter: true
    89        fetchRetry:
    90            initialBackoff: 500ms
    91            backoffFactor: 2
    92            maxRetries: 3
    93            jitter: true
    94        backgroundHealthCheckFailLimit: 4
    95        backgroundHealthCheckFailThrottleFactor: 0.5
    96        hashing:
    97          seed: 42
    98  
    99    gcPercentage: 100
   100  
   101    bootstrap:
   102        filesystem:
   103            numProcessorsPerCPU: 0.42
   104        commitlog:
   105            returnUnfulfilledForCorruptCommitLogFiles: false
   106  
   107    commitlog:
   108        flushMaxBytes: 524288
   109        flushEvery: 1s
   110        queue:
   111            calculationType: fixed
   112            size: 2097152
   113  
   114    filesystem:
   115        filePathPrefix: /var/lib/m3db
   116        writeBufferSize: 65536
   117        dataReadBufferSize: 65536
   118        infoReadBufferSize: 128
   119        seekReadBufferSize: 4096
   120        throughputLimitMbps: 100.0
   121        throughputCheckEvery: 128
   122        force_index_summaries_mmap_memory: true
   123        force_bloom_filter_mmap_memory: true
   124  
   125    repair:
   126        enabled: false
   127        throttle: 2m
   128        checkInterval: 1m
   129  
   130    pooling:
   131        blockAllocSize: 16
   132        thriftBytesPoolAllocSize: 2048
   133        type: simple
   134        seriesPool:
   135            size: 5242880
   136            lowWatermark: 0.01
   137            highWatermark: 0.02
   138        blockPool:
   139            size: 4194304
   140            lowWatermark: 0.01
   141            highWatermark: 0.02
   142        encoderPool:
   143            size: 25165824
   144            lowWatermark: 0.01
   145            highWatermark: 0.02
   146        checkedBytesWrapperPool:
   147            size: 65536
   148            lowWatermark: 0.01
   149            highWatermark: 0.02
   150        closersPool:
   151            size: 104857
   152            lowWatermark: 0.01
   153            highWatermark: 0.02
   154        contextPool:
   155            size: 524288
   156            lowWatermark: 0.01
   157            highWatermark: 0.02
   158        segmentReaderPool:
   159            size: 16384
   160            lowWatermark: 0.01
   161            highWatermark: 0.02
   162        iteratorPool:
   163            size: 2048
   164            lowWatermark: 0.01
   165            highWatermark: 0.02
   166        fetchBlockMetadataResultsPool:
   167            size: 65536
   168            capacity: 32
   169            lowWatermark: 0.01
   170            highWatermark: 0.02
   171        fetchBlocksMetadataResultsPool:
   172            size: 32
   173            lowWatermark: 0.01
   174            highWatermark: 0.02
   175            capacity: 4096
   176        replicaMetadataSlicePool:
   177            size: 131072
   178            capacity: 3
   179            lowWatermark: 0.01
   180            highWatermark: 0.02
   181        blockMetadataPool:
   182            size: 65536
   183            lowWatermark: 0.01
   184            highWatermark: 0.02
   185        blockMetadataSlicePool:
   186            size: 65536
   187            capacity: 32
   188            lowWatermark: 0.01
   189            highWatermark: 0.02
   190        blocksMetadataPool:
   191            size: 65536
   192            lowWatermark: 0.01
   193            highWatermark: 0.02
   194        blocksMetadataSlicePool:
   195            size: 32
   196            capacity: 4096
   197            lowWatermark: 0.01
   198            highWatermark: 0.02
   199        tagsPool:
   200            size: 65536
   201            capacity: 8
   202            maxCapacity: 32
   203            lowWatermark: 0.01
   204            highWatermark: 0.02
   205        tagIteratorPool:
   206            size: 8192
   207            lowWatermark: 0.01
   208            highWatermark: 0.02
   209        indexResultsPool:
   210            size: 8192
   211            lowWatermark: 0.01
   212            highWatermark: 0.02
   213        tagEncoderPool:
   214            size: 8192
   215            lowWatermark: 0.01
   216            highWatermark: 0.02
   217        tagDecoderPool:
   218            size: 8192
   219            lowWatermark: 0.01
   220            highWatermark: 0.02
   221        writeBatchPool:
   222            size: 8192
   223            initialBatchSize: 128
   224            maxBatchSize: 100000
   225        postingsListPool:
   226            size: 8
   227            lowWatermark: 0
   228            highWatermark: 0
   229        identifierPool:
   230            size: 9437184
   231            lowWatermark: 0.01
   232            highWatermark: 0.02
   233        bufferBucketPool:
   234            size: 65536
   235            lowWatermark: 0.01
   236            highWatermark: 0.02
   237        bufferBucketVersionsPool:
   238            size: 65536
   239            lowWatermark: 0.01
   240            highWatermark: 0.02
   241        retrieveRequestPool:
   242            size: 65536
   243            lowWatermark: 0.01
   244            highWatermark: 0.02
   245        bytesPool:
   246            buckets:
   247                - capacity: 16
   248                  size: 6291456
   249                  lowWatermark: 0.10
   250                  highWatermark: 0.12
   251                - capacity: 32
   252                  size: 3145728
   253                  lowWatermark: 0.10
   254                  highWatermark: 0.12
   255                - capacity: 64
   256                  size: 3145728
   257                  lowWatermark: 0.10
   258                  highWatermark: 0.12
   259                - capacity: 128
   260                  size: 3145728
   261                  lowWatermark: 0.10
   262                  highWatermark: 0.12
   263                - capacity: 256
   264                  size: 3145728
   265                  lowWatermark: 0.10
   266                  highWatermark: 0.12
   267                - capacity: 1440
   268                  size: 524288
   269                  lowWatermark: 0.10
   270                  highWatermark: 0.12
   271                - capacity: 4096
   272                  size: 524288
   273                  lowWatermark: 0.01
   274                  highWatermark: 0.02
   275                - capacity: 8192
   276                  size: 32768
   277                  lowWatermark: 0.01
   278                  highWatermark: 0.02
   279  
   280    discovery:
   281      config:
   282          service:
   283              env: production
   284              zone: embedded
   285              service: m3db
   286              cacheDir: /var/lib/m3kv
   287              etcdClusters:
   288                  - zone: embedded
   289                    endpoints:
   290                        - 1.1.1.1:2379
   291                        - 1.1.1.2:2379
   292                        - 1.1.1.3:2379
   293  
   294          seedNodes:
   295              listenPeerUrls:
   296                  - http://0.0.0.0:2380
   297              listenClientUrls:
   298                  - http://0.0.0.0:2379
   299              rootDir: /var/lib/etcd
   300              initialAdvertisePeerUrls:
   301                  - http://1.1.1.1:2380
   302              advertiseClientUrls:
   303                  - http://1.1.1.1:2379
   304              initialCluster:
   305                  - hostID: host1
   306                    endpoint: http://1.1.1.1:2380
   307                    clusterState: existing
   308                  - hostID: host2
   309                    endpoint: http://1.1.1.2:2380
   310                  - hostID: host3
   311                    endpoint: http://1.1.1.3:2380
   312    hashing:
   313      seed: 42
   314    writeNewSeriesAsync: true
   315    writeNewSeriesBackoffDuration: 2ms
   316    tracing:
   317      backend: jaeger
   318  `
   319  
   320  func TestConfiguration(t *testing.T) {
   321  	fd, err := ioutil.TempFile("", "config.yaml")
   322  	require.NoError(t, err)
   323  	defer func() {
   324  		assert.NoError(t, fd.Close())
   325  		assert.NoError(t, os.Remove(fd.Name()))
   326  	}()
   327  
   328  	_, err = fd.Write([]byte(testBaseConfig))
   329  	require.NoError(t, err)
   330  
   331  	// Verify is valid
   332  	var cfg Configuration
   333  	err = xconfig.LoadFile(&cfg, fd.Name(), xconfig.Options{})
   334  	require.NoError(t, err)
   335  
   336  	// Verify a reverse output of the data matches what we expect
   337  	data, err := yaml.Marshal(cfg)
   338  	require.NoError(t, err)
   339  
   340  	expected := `db:
   341    index:
   342      maxQueryIDsConcurrency: 0
   343      maxWorkerTime: 0s
   344      regexpDFALimit: null
   345      regexpFSALimit: null
   346      forwardIndexProbability: 0
   347      forwardIndexThreshold: 0
   348    transforms:
   349      truncateBy: none
   350      forceValue: null
   351    logging:
   352      file: /var/log/m3dbnode.log
   353      level: info
   354      fields: {}
   355    metrics:
   356      scope: null
   357      m3: null
   358      prometheus:
   359        handlerPath: /metrics
   360        listenAddress: ""
   361        timerType: ""
   362        defaultHistogramBuckets: []
   363        defaultSummaryObjectives: []
   364        onError: ""
   365      samplingRate: 1
   366      extended: detailed
   367      sanitization: prometheus
   368    listenAddress: 0.0.0.0:9000
   369    clusterListenAddress: 0.0.0.0:9001
   370    httpNodeListenAddress: 0.0.0.0:9002
   371    httpClusterListenAddress: 0.0.0.0:9003
   372    debugListenAddress: 0.0.0.0:9004
   373    hostID:
   374      resolver: config
   375      value: host1
   376      envVarName: null
   377      file: null
   378      hostname: null
   379    client:
   380      config: null
   381      writeConsistencyLevel: majority
   382      readConsistencyLevel: unstrict_majority
   383      connectConsistencyLevel: any
   384      writeTimeout: 10s
   385      fetchTimeout: 15s
   386      connectTimeout: 20s
   387      writeRetry:
   388        initialBackoff: 500ms
   389        backoffFactor: 3
   390        maxBackoff: 0s
   391        maxRetries: 2
   392        forever: null
   393        jitter: true
   394      fetchRetry:
   395        initialBackoff: 500ms
   396        backoffFactor: 2
   397        maxBackoff: 0s
   398        maxRetries: 3
   399        forever: null
   400        jitter: true
   401      logErrorSampleRate: 0
   402      logHostWriteErrorSampleRate: 0
   403      logHostFetchErrorSampleRate: 0
   404      backgroundHealthCheckFailLimit: 4
   405      backgroundHealthCheckFailThrottleFactor: 0.5
   406      hashing:
   407        seed: 42
   408      proto: null
   409      asyncWriteWorkerPoolSize: null
   410      asyncWriteMaxConcurrency: null
   411      useV2BatchAPIs: null
   412      writeTimestampOffset: null
   413      fetchSeriesBlocksBatchConcurrency: null
   414      fetchSeriesBlocksBatchSize: null
   415      writeShardsInitializing: null
   416      shardsLeavingCountTowardsConsistency: null
   417      shardsLeavingAndInitializingCountTowardsConsistency: null
   418      iterateEqualTimestampStrategy: null
   419    gcPercentage: 100
   420    tick: null
   421    bootstrap:
   422      mode: null
   423      filesystem:
   424        numProcessorsPerCPU: 0.42
   425        migration: null
   426      commitlog:
   427        returnUnfulfilledForCorruptCommitLogFiles: false
   428      peers: null
   429      cacheSeriesMetadata: null
   430      indexSegmentConcurrency: null
   431      verify: null
   432    blockRetrieve: null
   433    cache:
   434      series:
   435        policy: lru
   436        lru: null
   437      postingsList:
   438        size: 100
   439        cacheRegexp: false
   440        cacheTerms: false
   441        cacheSearch: null
   442      regexp: null
   443    filesystem:
   444      filePathPrefix: /var/lib/m3db
   445      writeBufferSize: 65536
   446      dataReadBufferSize: 65536
   447      infoReadBufferSize: 128
   448      seekReadBufferSize: 4096
   449      throughputLimitMbps: 100
   450      throughputCheckEvery: 128
   451      newFileMode: null
   452      newDirectoryMode: null
   453      mmap: null
   454      force_index_summaries_mmap_memory: true
   455      force_bloom_filter_mmap_memory: true
   456      bloomFilterFalsePositivePercent: null
   457    commitlog:
   458      flushMaxBytes: 524288
   459      flushEvery: 1s
   460      queue:
   461        calculationType: fixed
   462        size: 2097152
   463      queueChannel: null
   464    repair:
   465      enabled: false
   466      type: default
   467      strategy: default
   468      force: false
   469      throttle: 2m0s
   470      checkInterval: 1m0s
   471      concurrency: 0
   472      debugShadowComparisonsEnabled: false
   473      debugShadowComparisonsPercentage: 0
   474    replication: null
   475    pooling:
   476      blockAllocSize: 16
   477      thriftBytesPoolAllocSize: 2048
   478      type: simple
   479      bytesPool:
   480        buckets:
   481        - size: 6291456
   482          lowWatermark: 0.1
   483          highWatermark: 0.12
   484          capacity: 16
   485        - size: 3145728
   486          lowWatermark: 0.1
   487          highWatermark: 0.12
   488          capacity: 32
   489        - size: 3145728
   490          lowWatermark: 0.1
   491          highWatermark: 0.12
   492          capacity: 64
   493        - size: 3145728
   494          lowWatermark: 0.1
   495          highWatermark: 0.12
   496          capacity: 128
   497        - size: 3145728
   498          lowWatermark: 0.1
   499          highWatermark: 0.12
   500          capacity: 256
   501        - size: 524288
   502          lowWatermark: 0.1
   503          highWatermark: 0.12
   504          capacity: 1440
   505        - size: 524288
   506          lowWatermark: 0.01
   507          highWatermark: 0.02
   508          capacity: 4096
   509        - size: 32768
   510          lowWatermark: 0.01
   511          highWatermark: 0.02
   512          capacity: 8192
   513      checkedBytesWrapperPool:
   514        size: 65536
   515        lowWatermark: 0.01
   516        highWatermark: 0.02
   517      closersPool:
   518        size: 104857
   519        lowWatermark: 0.01
   520        highWatermark: 0.02
   521      contextPool:
   522        size: 524288
   523        lowWatermark: 0.01
   524        highWatermark: 0.02
   525      seriesPool:
   526        size: 5242880
   527        lowWatermark: 0.01
   528        highWatermark: 0.02
   529      blockPool:
   530        size: 4194304
   531        lowWatermark: 0.01
   532        highWatermark: 0.02
   533      encoderPool:
   534        size: 25165824
   535        lowWatermark: 0.01
   536        highWatermark: 0.02
   537      iteratorPool:
   538        size: 2048
   539        lowWatermark: 0.01
   540        highWatermark: 0.02
   541      segmentReaderPool:
   542        size: 16384
   543        lowWatermark: 0.01
   544        highWatermark: 0.02
   545      identifierPool:
   546        size: 9437184
   547        lowWatermark: 0.01
   548        highWatermark: 0.02
   549      fetchBlockMetadataResultsPool:
   550        size: 65536
   551        lowWatermark: 0.01
   552        highWatermark: 0.02
   553        capacity: 32
   554      fetchBlocksMetadataResultsPool:
   555        size: 32
   556        lowWatermark: 0.01
   557        highWatermark: 0.02
   558        capacity: 4096
   559      replicaMetadataSlicePool:
   560        size: 131072
   561        lowWatermark: 0.01
   562        highWatermark: 0.02
   563        capacity: 3
   564      blockMetadataPool:
   565        size: 65536
   566        lowWatermark: 0.01
   567        highWatermark: 0.02
   568      blockMetadataSlicePool:
   569        size: 65536
   570        lowWatermark: 0.01
   571        highWatermark: 0.02
   572        capacity: 32
   573      blocksMetadataPool:
   574        size: 65536
   575        lowWatermark: 0.01
   576        highWatermark: 0.02
   577      blocksMetadataSlicePool:
   578        size: 32
   579        lowWatermark: 0.01
   580        highWatermark: 0.02
   581        capacity: 4096
   582      tagsPool:
   583        size: 65536
   584        lowWatermark: 0.01
   585        highWatermark: 0.02
   586        capacity: 8
   587        maxCapacity: 32
   588      tagIteratorPool:
   589        size: 8192
   590        lowWatermark: 0.01
   591        highWatermark: 0.02
   592      indexResultsPool:
   593        size: 8192
   594        lowWatermark: 0.01
   595        highWatermark: 0.02
   596      tagEncoderPool:
   597        size: 8192
   598        lowWatermark: 0.01
   599        highWatermark: 0.02
   600      tagDecoderPool:
   601        size: 8192
   602        lowWatermark: 0.01
   603        highWatermark: 0.02
   604      writeBatchPool:
   605        size: 8192
   606        initialBatchSize: 128
   607        maxBatchSize: 100000
   608      bufferBucketPool:
   609        size: 65536
   610        lowWatermark: 0.01
   611        highWatermark: 0.02
   612      bufferBucketVersionsPool:
   613        size: 65536
   614        lowWatermark: 0.01
   615        highWatermark: 0.02
   616      retrieveRequestPool:
   617        size: 65536
   618        lowWatermark: 0.01
   619        highWatermark: 0.02
   620      postingsListPool:
   621        size: 8
   622        lowWatermark: 0
   623        highWatermark: 0
   624    discovery:
   625      type: null
   626      m3dbCluster: null
   627      m3AggregatorCluster: null
   628      config:
   629        services:
   630        - async: false
   631          clientOverrides:
   632            hostQueueFlushInterval: null
   633            targetHostQueueFlushSize: null
   634          service:
   635            zone: embedded
   636            env: production
   637            service: m3db
   638            cacheDir: /var/lib/m3kv
   639            etcdClusters:
   640            - zone: embedded
   641              endpoints:
   642              - 1.1.1.1:2379
   643              - 1.1.1.2:2379
   644              - 1.1.1.3:2379
   645              keepAlive: null
   646              tls: null
   647              autoSyncInterval: 0s
   648              dialTimeout: 0s
   649            m3sd:
   650              initTimeout: null
   651            watchWithRevision: 0
   652            newDirectoryMode: null
   653            retry:
   654              initialBackoff: 0s
   655              backoffFactor: 0
   656              maxBackoff: 0s
   657              maxRetries: 0
   658              forever: null
   659              jitter: null
   660            requestTimeout: 0s
   661            watchChanInitTimeout: 0s
   662            watchChanCheckInterval: 0s
   663            watchChanResetInterval: 0s
   664            enableFastGets: false
   665        statics: []
   666        seedNodes:
   667          rootDir: /var/lib/etcd
   668          initialAdvertisePeerUrls:
   669          - http://1.1.1.1:2380
   670          advertiseClientUrls:
   671          - http://1.1.1.1:2379
   672          listenPeerUrls:
   673          - http://0.0.0.0:2380
   674          listenClientUrls:
   675          - http://0.0.0.0:2379
   676          initialCluster:
   677          - hostID: host1
   678            endpoint: http://1.1.1.1:2380
   679            clusterState: existing
   680          - hostID: host2
   681            endpoint: http://1.1.1.2:2380
   682            clusterState: ""
   683          - hostID: host3
   684            endpoint: http://1.1.1.3:2380
   685            clusterState: ""
   686          clientTransportSecurity:
   687            caFile: ""
   688            certFile: ""
   689            keyFile: ""
   690            trustedCaFile: ""
   691            clientCertAuth: false
   692            autoTls: false
   693          peerTransportSecurity:
   694            caFile: ""
   695            certFile: ""
   696            keyFile: ""
   697            trustedCaFile: ""
   698            clientCertAuth: false
   699            autoTls: false
   700    hashing:
   701      seed: 42
   702    writeNewSeriesAsync: true
   703    writeNewSeriesBackoffDuration: 2ms
   704    proto: null
   705    tracing:
   706      serviceName: ""
   707      backend: jaeger
   708      opentelemetry:
   709        serviceName: ""
   710        endpoint: ""
   711        insecure: false
   712        attributes: {}
   713      jaeger:
   714        serviceName: ""
   715        disabled: false
   716        rpc_metrics: false
   717        traceid_128bit: false
   718        tags: []
   719        sampler: null
   720        reporter: null
   721        headers: null
   722        baggage_restrictions: null
   723        throttler: null
   724      lightstep:
   725        access_token: ""
   726        collector:
   727          scheme: ""
   728          host: ""
   729          port: 0
   730          plaintext: false
   731          custom_ca_cert_file: ""
   732        tags: {}
   733        lightstep_api:
   734          scheme: ""
   735          host: ""
   736          port: 0
   737          plaintext: false
   738          custom_ca_cert_file: ""
   739        max_buffered_spans: 0
   740        max_log_key_len: 0
   741        max_log_value_len: 0
   742        max_logs_per_span: 0
   743        grpc_max_call_send_msg_size_bytes: 0
   744        reporting_period: 0s
   745        min_reporting_period: 0s
   746        report_timeout: 0s
   747        drop_span_logs: false
   748        verbose: false
   749        use_http: false
   750        usegrpc: false
   751        reconnect_period: 0s
   752        meta_event_reporting_enabled: false
   753    limits:
   754      maxRecentlyQueriedSeriesDiskBytesRead: null
   755      maxRecentlyQueriedSeriesDiskRead: null
   756      maxRecentlyQueriedSeriesBlocks: null
   757      maxRecentlyQueriedMetadata: null
   758      maxOutstandingWriteRequests: 0
   759      maxOutstandingReadRequests: 0
   760      maxOutstandingRepairedBytes: 0
   761      maxEncodersPerBlock: 0
   762      writeNewSeriesPerSecond: 0
   763    tchannel: null
   764    debug:
   765      mutexProfileFraction: 0
   766      blockProfileRate: 0
   767    forceColdWritesEnabled: null
   768  coordinator: null
   769  `
   770  
   771  	actual := string(data)
   772  	if expected != actual {
   773  		diff := xtest.Diff(expected, actual)
   774  		require.FailNow(t, "reverse config did not match:\n"+diff)
   775  	}
   776  }
   777  
   778  func TestInitialClusterEndpoints(t *testing.T) {
   779  	seedNodes := []environment.SeedNode{
   780  		{
   781  			HostID:   "host1",
   782  			Endpoint: "http://1.1.1.1:2380",
   783  		},
   784  	}
   785  	endpoints, err := InitialClusterEndpoints(seedNodes)
   786  	require.NoError(t, err)
   787  	require.NotNil(t, endpoints)
   788  	require.Equal(t, 1, len(endpoints))
   789  	assert.Equal(t, "http://1.1.1.1:2379", endpoints[0])
   790  
   791  	seedNodes = []environment.SeedNode{
   792  		{
   793  			HostID:   "host1",
   794  			Endpoint: "http://1.1.1.1:2380",
   795  		},
   796  		{
   797  			HostID:   "host2",
   798  			Endpoint: "http://1.1.1.2:2380",
   799  		},
   800  		{
   801  			HostID:   "host3",
   802  			Endpoint: "http://1.1.1.3:2380",
   803  		},
   804  	}
   805  	endpoints, err = InitialClusterEndpoints(seedNodes)
   806  	require.NoError(t, err)
   807  	require.NotNil(t, endpoints)
   808  	require.Equal(t, 3, len(endpoints))
   809  	assert.Equal(t, "http://1.1.1.1:2379", endpoints[0])
   810  	assert.Equal(t, "http://1.1.1.2:2379", endpoints[1])
   811  	assert.Equal(t, "http://1.1.1.3:2379", endpoints[2])
   812  
   813  	seedNodes = []environment.SeedNode{}
   814  	endpoints, err = InitialClusterEndpoints(seedNodes)
   815  	assert.NoError(t, err)
   816  	assert.Equal(t, 0, len(endpoints))
   817  
   818  	seedNodes = []environment.SeedNode{
   819  		{
   820  			HostID:   "host1",
   821  			Endpoint: "",
   822  		},
   823  	}
   824  	_, err = InitialClusterEndpoints(seedNodes)
   825  	require.Error(t, err)
   826  }
   827  
   828  func TestIsSeedNode(t *testing.T) {
   829  	seedNodes := []environment.SeedNode{
   830  		{
   831  			HostID:   "host1",
   832  			Endpoint: "http://1.1.1.1:2380",
   833  		},
   834  	}
   835  	res := IsSeedNode(seedNodes, "host1")
   836  	assert.Equal(t, true, res)
   837  
   838  	seedNodes = []environment.SeedNode{
   839  		{
   840  			HostID:   "host1",
   841  			Endpoint: "http://1.1.1.1:2380",
   842  		},
   843  		{
   844  			HostID:   "host2",
   845  			Endpoint: "http://1.1.1.2:2380",
   846  		},
   847  		{
   848  			HostID:   "host3",
   849  			Endpoint: "http://1.1.1.3:2380",
   850  		},
   851  	}
   852  	res = IsSeedNode(seedNodes, "host2")
   853  	assert.Equal(t, true, res)
   854  
   855  	seedNodes = []environment.SeedNode{
   856  		{
   857  			HostID:   "host1",
   858  			Endpoint: "http://1.1.1.1:2380",
   859  		},
   860  		{
   861  			HostID:   "host2",
   862  			Endpoint: "http://1.1.1.2:2380",
   863  		},
   864  	}
   865  	res = IsSeedNode(seedNodes, "host4")
   866  	assert.Equal(t, false, res)
   867  }
   868  
   869  func TestGetHostAndEndpointFromID(t *testing.T) {
   870  	test2Seeds := []environment.SeedNode{
   871  		{
   872  			HostID:       "host1",
   873  			Endpoint:     "http://1.1.1.1:2380",
   874  			ClusterState: "existing",
   875  		},
   876  		{
   877  			HostID:   "host2",
   878  			Endpoint: "http://1.1.1.2:2380",
   879  		},
   880  	}
   881  
   882  	tests := []struct {
   883  		initialCluster []environment.SeedNode
   884  		hostID         string
   885  		expSeedNode    environment.SeedNode
   886  		expEndpoint    string
   887  		expErr         bool
   888  	}{
   889  		{
   890  			initialCluster: test2Seeds,
   891  			hostID:         "host1",
   892  			expSeedNode:    test2Seeds[0],
   893  			expEndpoint:    "http://1.1.1.1",
   894  		},
   895  		{
   896  			initialCluster: test2Seeds,
   897  			hostID:         "host3",
   898  			expErr:         true,
   899  		},
   900  		{
   901  			initialCluster: test2Seeds[:0],
   902  			hostID:         "host1",
   903  			expErr:         true,
   904  		},
   905  	}
   906  
   907  	for _, test := range tests {
   908  		node, ep, err := getHostAndEndpointFromID(test.initialCluster, test.hostID)
   909  		if test.expErr {
   910  			assert.Error(t, err)
   911  			continue
   912  		}
   913  
   914  		assert.Equal(t, test.expSeedNode, node)
   915  		assert.Equal(t, test.expEndpoint, ep)
   916  	}
   917  }
   918  
   919  func TestNewEtcdEmbedConfig(t *testing.T) {
   920  	fd, err := ioutil.TempFile("", "config2.yaml")
   921  	require.NoError(t, err)
   922  	defer func() {
   923  		assert.NoError(t, fd.Close())
   924  		assert.NoError(t, os.Remove(fd.Name()))
   925  	}()
   926  
   927  	_, err = fd.Write([]byte(testBaseConfig))
   928  	require.NoError(t, err)
   929  
   930  	// Verify is valid
   931  	var cfg Configuration
   932  	err = xconfig.LoadFile(&cfg, fd.Name(), xconfig.Options{})
   933  	require.NoError(t, err)
   934  
   935  	embedCfg, err := NewEtcdEmbedConfig(*cfg.DB)
   936  	require.NoError(t, err)
   937  
   938  	assert.Equal(t, "existing", embedCfg.ClusterState)
   939  }
   940  
   941  func TestNewJaegerTracer(t *testing.T) {
   942  	fd, err := ioutil.TempFile("", "config_jaeger.yaml")
   943  	require.NoError(t, err)
   944  	defer func() {
   945  		assert.NoError(t, fd.Close())
   946  		assert.NoError(t, os.Remove(fd.Name()))
   947  	}()
   948  
   949  	_, err = fd.Write([]byte(testBaseConfig))
   950  	require.NoError(t, err)
   951  
   952  	// Verify is valid
   953  	var cfg Configuration
   954  	err = xconfig.LoadFile(&cfg, fd.Name(), xconfig.Options{})
   955  	require.NoError(t, err)
   956  
   957  	instrumentOpts := instrument.NewOptions()
   958  	tracer, closer, err := cfg.DB.Tracing.NewTracer("m3dbnode",
   959  		instrumentOpts.MetricsScope(), instrumentOpts.Logger())
   960  	require.NoError(t, err)
   961  	defer closer.Close()
   962  
   963  	// Verify tracer gets created
   964  	require.NotNil(t, tracer)
   965  }
   966  
   967  func TestProtoConfig(t *testing.T) {
   968  	testProtoConf := `
   969  db:
   970    metrics:
   971        samplingRate: 1.0
   972  
   973    listenAddress: 0.0.0.0:9000
   974    clusterListenAddress: 0.0.0.0:9001
   975    httpNodeListenAddress: 0.0.0.0:9002
   976    httpClusterListenAddress: 0.0.0.0:9003
   977  
   978    commitlog:
   979        flushMaxBytes: 524288
   980        flushEvery: 1s
   981        queue:
   982            size: 2097152
   983  
   984    proto:
   985        enabled: false
   986        schema_registry:
   987           "ns1:2d":
   988              schemaFilePath: "file/path/to/ns1/schema"
   989              messageName: "ns1_msg_name"
   990           ns2:
   991              schemaFilePath: "file/path/to/ns2/schema"
   992              messageName: "ns2_msg_name"
   993  `
   994  	fd, err := ioutil.TempFile("", "config_proto.yaml")
   995  	require.NoError(t, err)
   996  	defer func() {
   997  		assert.NoError(t, fd.Close())
   998  		assert.NoError(t, os.Remove(fd.Name()))
   999  	}()
  1000  
  1001  	_, err = fd.Write([]byte(testProtoConf))
  1002  	require.NoError(t, err)
  1003  
  1004  	// Verify is valid
  1005  	var cfg Configuration
  1006  	err = xconfig.LoadFile(&cfg, fd.Name(), xconfig.Options{})
  1007  	require.NoError(t, err)
  1008  
  1009  	require.NotNil(t, cfg.DB.Proto)
  1010  	require.False(t, cfg.DB.Proto.Enabled)
  1011  
  1012  	require.Len(t, cfg.DB.Proto.SchemaRegistry, 2)
  1013  	require.EqualValues(t, map[string]NamespaceProtoSchema{
  1014  		"ns1:2d": {
  1015  			SchemaFilePath: "file/path/to/ns1/schema",
  1016  			MessageName:    "ns1_msg_name",
  1017  		},
  1018  		"ns2": {
  1019  			SchemaFilePath: "file/path/to/ns2/schema",
  1020  			MessageName:    "ns2_msg_name",
  1021  		},
  1022  	}, cfg.DB.Proto.SchemaRegistry)
  1023  }
  1024  
  1025  func TestBootstrapCommitLogConfig(t *testing.T) {
  1026  	ctrl := gomock.NewController(t)
  1027  	defer ctrl.Finish()
  1028  
  1029  	notDefault := !commitlog.DefaultReturnUnfulfilledForCorruptCommitLogFiles
  1030  	notDefaultStr := fmt.Sprintf("%v", notDefault)
  1031  
  1032  	testConf := `
  1033  db:
  1034    metrics:
  1035        samplingRate: 1.0
  1036  
  1037    listenAddress: 0.0.0.0:9000
  1038    clusterListenAddress: 0.0.0.0:9001
  1039    httpNodeListenAddress: 0.0.0.0:9002
  1040    httpClusterListenAddress: 0.0.0.0:9003
  1041  
  1042    bootstrap:
  1043        commitlog:
  1044            returnUnfulfilledForCorruptCommitLogFiles: ` + notDefaultStr + `
  1045  
  1046    commitlog:
  1047        flushMaxBytes: 524288
  1048        flushEvery: 1s
  1049        queue:
  1050            size: 2097152
  1051  `
  1052  	fd, err := ioutil.TempFile("", "config.yaml")
  1053  	require.NoError(t, err)
  1054  	defer func() {
  1055  		assert.NoError(t, fd.Close())
  1056  		assert.NoError(t, os.Remove(fd.Name()))
  1057  	}()
  1058  
  1059  	_, err = fd.Write([]byte(testConf))
  1060  	require.NoError(t, err)
  1061  
  1062  	// Verify is valid
  1063  	var cfg Configuration
  1064  	err = xconfig.LoadFile(&cfg, fd.Name(), xconfig.Options{})
  1065  	require.NoError(t, err)
  1066  	require.NotNil(t, cfg.DB)
  1067  
  1068  	mapProvider := topology.NewMockMapProvider(ctrl)
  1069  	origin := topology.NewMockHost(ctrl)
  1070  	adminClient := client.NewMockAdminClient(ctrl)
  1071  
  1072  	_, err = cfg.DB.Bootstrap.New(
  1073  		result.NewOptions(),
  1074  		storage.DefaultTestOptions(),
  1075  		mapProvider,
  1076  		origin,
  1077  		adminClient,
  1078  	)
  1079  	require.NoError(t, err)
  1080  }
  1081  
  1082  func TestConfigurationComponents(t *testing.T) {
  1083  	testConfDB := `
  1084  db: {}
  1085  `
  1086  	testConfMultiple := `
  1087  coordinator: {}
  1088  db: {}
  1089  `
  1090  	tests := []struct {
  1091  		name       string
  1092  		conf       string
  1093  		components int
  1094  	}{
  1095  		{
  1096  			name:       "db configuration",
  1097  			conf:       testConfDB,
  1098  			components: 1,
  1099  		},
  1100  		{
  1101  			name:       "coordinator and db configuration",
  1102  			conf:       testConfMultiple,
  1103  			components: 2,
  1104  		},
  1105  	}
  1106  
  1107  	for _, tt := range tests {
  1108  		t.Run(tt.name, func(t *testing.T) {
  1109  			fd, err := ioutil.TempFile("", "config.yaml")
  1110  			require.NoError(t, err)
  1111  			defer func() {
  1112  				assert.NoError(t, fd.Close())
  1113  				assert.NoError(t, os.Remove(fd.Name()))
  1114  			}()
  1115  
  1116  			_, err = fd.WriteString(tt.conf)
  1117  			require.NoError(t, err)
  1118  
  1119  			var cfg Configuration
  1120  			err = xconfig.LoadFile(&cfg, fd.Name(), xconfig.Options{})
  1121  			require.NoError(t, err)
  1122  
  1123  			require.Equal(t, tt.components, cfg.Components())
  1124  		})
  1125  	}
  1126  }