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